2025-04-27 07:49:33 -04:00

1261 lines
34 KiB
C

/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
**
** mlink.c
** Remote Access Common Dialog APIs
** Multi-link configuration dialogs
**
** 01/23/96 Steve Cobb
*/
#include "rasdlgp.h"
/*----------------------------------------------------------------------------
** Help maps
**----------------------------------------------------------------------------
*/
static DWORD g_adwMlHelp[] =
{
CID_ML_ST_Devices, HID_ML_LV_Devices,
CID_ML_LV_Devices, HID_ML_LV_Devices,
CID_ML_PB_Edit, HID_ML_PB_Edit,
CID_ML_PB_Configure, HID_ML_PB_Configure,
0, 0
};
static DWORD g_adwDmHelp[] =
{
CID_DM_RB_DialAll, HID_DM_RB_DialAll,
CID_DM_RB_DialAsNeeded, HID_DM_RB_DialAsNeeded,
CID_DM_ST_Dial, HID_DM_ST_Dial,
CID_DM_LB_DialPercent, HID_DM_LB_DialPercent,
CID_DM_ST_DialOrMore, HID_DM_LB_DialPercent,
CID_DM_EB_DialMinutes, HID_DM_EB_DialMinutes,
CID_DM_ST_DialMinutes, HID_DM_EB_DialMinutes,
CID_DM_ST_HangUp, HID_DM_ST_HangUp,
CID_DM_LB_HangUpPercent, HID_DM_LB_HangUpPercent,
CID_DM_ST_HangUpOrLess, HID_DM_LB_HangUpPercent,
CID_DM_EB_HangUpMinutes, HID_DM_EB_HangUpMinutes,
CID_DM_ST_HangUpMinutes, HID_DM_EB_HangUpMinutes,
0, 0
};
/*----------------------------------------------------------------------------
** Local datatypes (alphabetically)
**----------------------------------------------------------------------------
*/
/* Multi-link configuration dialog argument block.
*/
#define MLARGS struct tagMLARGS
MLARGS
{
DTLLIST* pList;
BOOL fRouter;
};
/* Multi-link configuration dialog context block.
*/
#define MLINFO struct tagMLINFO
MLINFO
{
/* Stub API arguments.
*/
DTLLIST* pList;
BOOL fRouter;
/* Handle of this dialog and some of it's controls.
*/
HWND hwndDlg;
HWND hwndLv;
HWND hwndPbEdit;
HWND hwndPbConfigure;
BOOL fChecksInstalled;
};
/* Multi-link dialing dialog context block.
*/
#define DMINFO struct tagDMINFO
DMINFO
{
/* Stub API argument.
*/
PBENTRY* pEntry;
/* Handle of this dialog and some of it's controls.
*/
HWND hwndDlg;
HWND hwndRbDialAll;
HWND hwndRbDialAsNeeded;
HWND hwndStDial;
HWND hwndLbDialPercent;
HWND hwndStDialOrMore;
HWND hwndEbDialMinutes;
HWND hwndStDialMinutes;
HWND hwndStHangUp;
HWND hwndLbHangUpPercent;
HWND hwndStHangUpOrLess;
HWND hwndEbHangUpMinutes;
HWND hwndStHangUpMinutes;
};
/*----------------------------------------------------------------------------
** Local prototypes (alphabetically)
**----------------------------------------------------------------------------
*/
INT_PTR CALLBACK
DmDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam );
BOOL
DmCommand(
IN HWND hwnd,
IN WORD wNotification,
IN WORD wId,
IN HWND hwndCtrl );
BOOL
DmInit(
IN HWND hwndDlg,
IN PBENTRY* pEntry );
VOID
DmSave(
IN DMINFO* pInfo );
VOID
DmTerm(
IN HWND hwndDlg );
VOID
DmUpdateAsNeededState(
IN DMINFO* pInfo );
INT_PTR CALLBACK
MlDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam );
BOOL
MlCommand(
IN HWND hwnd,
IN WORD wNotification,
IN WORD wId,
IN HWND hwndCtrl );
VOID
MlFillLv(
IN MLINFO* pInfo );
BOOL
MlInit(
IN HWND hwndDlg,
IN MLARGS* pArgs );
LVXDRAWINFO*
MlLvCallback(
IN HWND hwndLv,
IN DWORD dwItem );
VOID
MlPbConfigure(
IN MLINFO* pInfo );
VOID
MlPbEdit(
IN MLINFO* pInfo );
VOID
MlSave(
IN MLINFO* pInfo );
VOID
MlTerm(
IN HWND hwndDlg );
VOID
MlUpdatePbState(
IN MLINFO* pInfo );
/*----------------------------------------------------------------------------
** Multi-link configuration dialog
** Listed alphabetically following stub API and dialog proc
**----------------------------------------------------------------------------
*/
BOOL
MultiLinkConfigureDlg(
IN HWND hwndOwner,
IN DTLLIST* pListLinks,
IN BOOL fRouter )
/* Popup the Multi-link configuration dialog. 'HwndOwner' is the owner of
** the dialog. 'PListLinks' is a list of PBLINKs to edit. 'FRouter'
** indicates router-style labels should be used rather than client-style.
**
** Returns true if user pressed OK and succeeded, false if user pressed
** Cancel or encountered an error.
*/
{
MLARGS args;
int nStatus;
TRACE("MultiLinkConfigureDlg");
args.pList = pListLinks;
args.fRouter = fRouter;
nStatus =
(BOOL )DialogBoxParam(
g_hinstDll,
MAKEINTRESOURCE( DID_ML_MultiLink ),
hwndOwner,
MlDlgProc,
(LPARAM )&args );
if (nStatus == -1)
{
ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
nStatus = FALSE;
}
return (BOOL )nStatus;
}
INT_PTR CALLBACK
MlDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam )
/* DialogProc callback for the Multi-Link Configure dialog. Parameters
** and return value are as described for standard windows 'DialogProc's.
*/
{
#if 0
TRACE4("MlDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
(DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
#endif
if (ListView_OwnerHandler(
hwnd, unMsg, wparam, lparam, MlLvCallback ))
{
return TRUE;
}
switch (unMsg)
{
case WM_INITDIALOG:
return MlInit( hwnd, (MLARGS* )lparam );
case WM_HELP:
case WM_CONTEXTMENU:
ContextHelp( g_adwMlHelp, hwnd, unMsg, wparam, lparam );
break;
case WM_COMMAND:
{
return MlCommand(
hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
}
case WM_NOTIFY:
{
switch (((NMHDR* )lparam)->code)
{
case LVN_ITEMCHANGED:
{
MLINFO* pInfo = (MLINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
MlUpdatePbState( pInfo );
return TRUE;
}
}
break;
}
case WM_DESTROY:
{
MlTerm( hwnd );
break;
}
}
return FALSE;
}
BOOL
MlCommand(
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;
TRACE2("DmCommand(n=%d,i=%d)",
(DWORD)wNotification,(DWORD)wId);
switch (wId)
{
case CID_ML_PB_Edit:
{
MLINFO* pInfo = (MLINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
MlPbEdit( pInfo );
return TRUE;
}
case CID_ML_PB_Configure:
{
MLINFO* pInfo = (MLINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
MlPbConfigure( pInfo );
return TRUE;
}
case IDOK:
{
MLINFO* pInfo;
TRACE("OK pressed");
pInfo = (MLINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
if (ListView_GetCheckedCount( pInfo->hwndLv ) <= 0)
{
MsgDlg( pInfo->hwndDlg, SID_SelectOneLink, NULL );
return TRUE;
}
MlSave( pInfo );
EndDialog( hwnd, TRUE );
return TRUE;
}
case IDCANCEL:
{
TRACE("Cancel pressed");
EndDialog( hwnd, FALSE );
return TRUE;
}
}
return FALSE;
}
VOID
MlFillLv(
IN MLINFO* pInfo )
/* Fill the listview with devices and phone numbers. 'PInfo' is the
** dialog context.
**
** Note: This routine should be called only once.
*/
{
INT iItem;
DTLLIST* pListLinks;
DTLNODE* pNode;
TRACE("MlFillLv");
ListView_DeleteAllItems( pInfo->hwndLv );
/* Install "listview of check boxes" handling.
*/
pInfo->fChecksInstalled =
ListView_InstallChecks( pInfo->hwndLv, g_hinstDll );
if (!pInfo->fChecksInstalled)
return;
/* Add columns.
*/
{
LV_COLUMN col;
TCHAR* pszHeader0;
TCHAR* pszHeader1;
pszHeader0 = PszFromId( g_hinstDll, SID_DeviceColHead );
pszHeader1 = PszFromId( g_hinstDll, SID_PhoneNumbersColHead );
ZeroMemory( &col, sizeof(col) );
col.mask = LVCF_FMT + LVCF_TEXT;
col.fmt = LVCFMT_LEFT;
col.pszText = (pszHeader0) ? pszHeader0 : TEXT("");
ListView_InsertColumn( pInfo->hwndLv, 0, &col );
ZeroMemory( &col, sizeof(col) );
col.mask = LVCF_FMT + LVCF_SUBITEM + LVCF_TEXT;
col.fmt = LVCFMT_LEFT;
col.pszText = (pszHeader1) ? pszHeader1 : TEXT("");
col.iSubItem = 1;
ListView_InsertColumn( pInfo->hwndLv, 1, &col );
Free0( pszHeader0 );
Free0( pszHeader1 );
}
/* Add the modem and adapter images.
*/
ListView_SetDeviceImageList( pInfo->hwndLv, g_hinstDll );
/* Duplicate caller's list of links.
*/
pListLinks = DtlDuplicateList(
pInfo->pList, DuplicateLinkNode, DestroyLinkNode );
if (!pListLinks)
{
ErrorDlg( pInfo->hwndDlg, SID_OP_LoadDlg,
ERROR_NOT_ENOUGH_MEMORY, NULL );
EndDialog( pInfo->hwndDlg, FALSE );
return;
}
/* Add each link to the listview.
*/
for (pNode = DtlGetFirstNode( pListLinks ), iItem = 0;
pNode;
pNode = DtlGetNextNode( pNode ), ++iItem)
{
PBLINK* pLink;
LV_ITEM item;
TCHAR* psz;
pLink = (PBLINK* )DtlGetData( pNode );
ZeroMemory( &item, sizeof(item) );
item.mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM;
item.iItem = iItem;
psz = DisplayPszFromDeviceAndPort(
pLink->pbport.pszDevice, pLink->pbport.pszPort );
if (!psz)
continue;
item.pszText = psz;
item.iImage =
(pLink->pbport.pbdevicetype == PBDT_Modem)
? DI_Modem : DI_Adapter;
item.lParam = (LPARAM )pNode;
ListView_InsertItem( pInfo->hwndLv, &item );
Free( psz );
psz = PszFromPhoneNumberList( pLink->pdtllistPhoneNumbers );
if (psz)
{
ListView_SetItemText( pInfo->hwndLv, iItem, 1, psz );
Free( psz );
}
ListView_SetCheck( pInfo->hwndLv, iItem, pLink->fEnabled );
}
/* Auto-size columns to look good with the text they contain.
*/
ListView_SetColumnWidth( pInfo->hwndLv, 0, LVSCW_AUTOSIZE_USEHEADER );
ListView_SetColumnWidth( pInfo->hwndLv, 1, LVSCW_AUTOSIZE_USEHEADER );
/* Select the first item.
*/
ListView_SetItemState( pInfo->hwndLv, 0, LVIS_SELECTED, LVIS_SELECTED );
}
BOOL
MlInit(
IN HWND hwndDlg,
IN MLARGS* pArgs )
/* Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
** 'PArgs' is the caller's stub API argument block.
**
** Return false if focus was set, true otherwise, i.e. as defined for
** WM_INITDIALOG.
*/
{
DWORD dwErr;
MLINFO* pInfo;
TRACE("MlInit");
/* 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->pList = pArgs->pList;
pInfo->fRouter = pArgs->fRouter;
pInfo->hwndDlg = hwndDlg;
SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo );
TRACE("Context set");
}
pInfo->hwndLv = GetDlgItem( hwndDlg, CID_ML_LV_Devices );
ASSERT(pInfo->hwndLv);
pInfo->hwndPbEdit = GetDlgItem( hwndDlg, CID_ML_PB_Edit );
ASSERT(pInfo->hwndPbEdit);
pInfo->hwndPbConfigure = GetDlgItem( hwndDlg, CID_ML_PB_Configure );
ASSERT(pInfo->hwndPbConfigure);
/* Initialize the list view, selecting the first item.
*/
MlFillLv( pInfo );
/* Position the dialog at our standard offset from the owner.
*/
{
HWND hwndOwner;
RECT rect;
hwndOwner = GetParent( hwndDlg );
ASSERT(hwndOwner);
GetWindowRect( hwndOwner, &rect );
PositionDlg( hwndDlg, TRUE, rect.left + DXSHEET, rect.top + DYSHEET );
}
/* 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;
}
LVXDRAWINFO*
MlLvCallback(
IN HWND hwndLv,
IN DWORD dwItem )
/* Enhanced list view callback to report drawing information. 'HwndLv' is
** the handle of the list view control. 'DwItem' is the index of the item
** being drawn.
**
** Returns the address of the column information.
*/
{
/* Use "wide selection bar" feature and the other recommended options.
**
** Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'.
*/
static LVXDRAWINFO info =
{ 2, 0, LVXDI_DxFill, { 0, 0 } };
return &info;
}
VOID
MlPbConfigure(
IN MLINFO* pInfo )
/* Called when the Configure button is pressed.
*/
{
DTLNODE* pNode;
PBLINK* pLinkFirst;
TRACE("MlPbConfigure");
pNode = (DTLNODE* )ListView_GetSelectedParamPtr( pInfo->hwndLv );
ASSERT(pNode);
pLinkFirst = (PBLINK* )DtlGetData( pNode );
ASSERT(pLinkFirst);
if (DeviceConfigureDlg( pInfo->hwndDlg, pLinkFirst, FALSE ))
{
if (ListView_GetSelectedCount( pInfo->hwndLv ) > 1)
{
INT i;
/* OK pressed on configure dialog and multiple items were
** selected. Transfer changes to other selected items.
*/
i = ListView_GetNextItem( pInfo->hwndLv, -1, LVNI_SELECTED );
while ((i = ListView_GetNextItem(
pInfo->hwndLv, i, LVNI_SELECTED )) >= 0)
{
LV_ITEM item;
PBLINK* pLink;
ZeroMemory( &item, sizeof(item) );
item.mask = LVIF_PARAM;
item.iItem = i;
if (!ListView_GetItem( pInfo->hwndLv, &item ))
break;
ASSERT(item.lParam);
pLink = (PBLINK* )DtlGetData( (DTLNODE* )item.lParam );
ASSERT(pLink);
ASSERT(pLink->pbport.pbdevicetype==PBDT_Isdn);
pLink->lLineType = pLinkFirst->lLineType;
pLink->fFallback = pLinkFirst->fFallback;
}
}
}
}
VOID
MlPbEdit(
IN MLINFO* pInfo )
/* Called when the Edit button is pressed.
*/
{
INT i;
DTLNODE* pNode;
PBLINK* pLink;
PBLINK* pFirstLink;
TRACE("MlPbEdit");
/* Get the first selected link and edit the phonenumber list and option.
*/
i = ListView_GetNextItem( pInfo->hwndLv, -1, LVNI_SELECTED );
ASSERT(i>=0);
pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLv, i );
ASSERT(pNode);
pFirstLink = (PBLINK* )DtlGetData( pNode );
ASSERT(pFirstLink);
if (PhoneNumberDlg(
pInfo->hwndDlg,
pInfo->fRouter,
pFirstLink->pdtllistPhoneNumbers,
&pFirstLink->fPromoteHuntNumbers ))
{
TCHAR* psz;
/* User pressed OK on phone number list dialog so update the phone
** number column text.
*/
psz = PszFromPhoneNumberList( pFirstLink->pdtllistPhoneNumbers );
if (psz)
{
ListView_SetItemText( pInfo->hwndLv, i, 1, psz );
Free( psz );
}
/* Duplicate the first selected links new phone number information to
** any other selected links.
*/
while ((i = ListView_GetNextItem(
pInfo->hwndLv, i, LVNI_SELECTED )) >= 0)
{
DTLLIST* pList;
pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLv, i );
ASSERT(pNode);
pLink = (PBLINK* )DtlGetData( pNode );
ASSERT(pLink);
pList = DtlDuplicateList( pFirstLink->pdtllistPhoneNumbers,
DuplicatePszNode, DestroyPszNode );
if (!pList)
break;
DtlDestroyList( pLink->pdtllistPhoneNumbers, DestroyPszNode );
pLink->pdtllistPhoneNumbers = pList;
pLink->fPromoteHuntNumbers = pFirstLink->fPromoteHuntNumbers;
psz = PszFromPhoneNumberList( pLink->pdtllistPhoneNumbers );
if (psz)
{
ListView_SetItemText( pInfo->hwndLv, i, 1, psz );
Free( psz );
}
}
}
}
VOID
MlSave(
IN MLINFO* pInfo )
/* Save control settings in caller's list of links. 'PInfo' is the dialog
** context.
*/
{
INT i;
DTLLIST* pList;
DTLNODE* pNode;
DTLNODE* pNodeCheck;
TRACE("MlSave");
while (pNode = DtlGetFirstNode( pInfo->pList ))
{
DtlRemoveNode( pInfo->pList, pNode );
DestroyLinkNode( pNode );
}
i = -1;
pNodeCheck = NULL;
while ((i = ListView_GetNextItem( pInfo->hwndLv, i, LVNI_ALL )) >= 0)
{
LV_ITEM item;
PBLINK* pLink;
ZeroMemory( &item, sizeof(item) );
item.mask = LVIF_PARAM;
item.iItem = i;
if (!ListView_GetItem( pInfo->hwndLv, &item ))
continue;
pNode = (DTLNODE* )item.lParam;
ASSERT(pNode);
pLink = (PBLINK* )DtlGetData( pNode );
ASSERT(pLink);
pLink->fEnabled = ListView_GetCheck( pInfo->hwndLv, i );
/* Save with checkeds followed by uncheckeds.
*/
if (pLink->fEnabled)
{
DtlAddNodeAfter( pInfo->pList, pNodeCheck, pNode );
pNodeCheck = (DTLNODE* )item.lParam;
}
else
{
DtlAddNodeLast( pInfo->pList, (DTLNODE* )item.lParam );
}
}
/* Delete all the items from the listview so MlTerm doesn't free them
** during clean up.
*/
while ((i = ListView_GetNextItem( pInfo->hwndLv, -1, LVNI_ALL )) >= 0)
ListView_DeleteItem( pInfo->hwndLv, i );
}
VOID
MlTerm(
IN HWND hwndDlg )
/* Dialog termination. Releases the context block. 'HwndDlg' is the
** handle of a dialog.
*/
{
MLINFO* pInfo;
TRACE("MlTerm");
pInfo = (MLINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
if (pInfo)
{
INT i;
/* Release any link nodes still in the list, e.g. if user Canceled.
*/
i = -1;
while ((i = ListView_GetNextItem( pInfo->hwndLv, i, LVNI_ALL )) >= 0)
{
DTLNODE* pNode;
pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLv, i );
DestroyLinkNode( pNode );
}
if (pInfo->fChecksInstalled)
ListView_UninstallChecks( pInfo->hwndLv );
Free( pInfo );
TRACE("Context freed");
}
}
VOID
MlUpdatePbState(
IN MLINFO* pInfo )
/* Enable/disable Edit and Configure button based on ListView selection.
** 'PInfo' is the dialog context.
*/
{
BOOL fEnableEdit;
BOOL fEnableConfigure;
UINT unSels;
INT i;
TRACE("MlUpdatePbState");
fEnableEdit = fEnableConfigure = FALSE;
unSels = ListView_GetSelectedCount( pInfo->hwndLv );
if (unSels <= 0)
{
/* No selected items so disable both buttons.
*/
fEnableEdit = fEnableConfigure = FALSE;
}
else
{
/* There's a selection.
*/
fEnableEdit = fEnableConfigure = TRUE;
if (unSels > 1)
{
/* There's more than one selection. Only ISDN lines are allowed
** to be simultaneously configured. (Could do RASMXS modems of
** the same type but for now we don't)
*/
i = -1;
while ((i = ListView_GetNextItem(
pInfo->hwndLv, i, LVNI_SELECTED )) >= 0)
{
LV_ITEM item;
DTLNODE* pNode;
PBLINK* pLink;
ZeroMemory( &item, sizeof(item) );
item.mask = LVIF_PARAM;
item.iItem = i;
if (!ListView_GetItem( pInfo->hwndLv, &item ))
continue;
pNode = (DTLNODE* )item.lParam;
if (!pNode)
{
/* If non-zero here it's because of the "set to NULL" in
** MlSave, which means we're wasting our time worrying
** about button state.
*/
return;
}
pLink = (PBLINK* )DtlGetData( pNode );
ASSERT(pLink);
if (pLink->pbport.pbdevicetype != PBDT_Isdn)
{
fEnableConfigure = FALSE;
break;
}
}
}
}
EnableWindow( pInfo->hwndPbEdit, fEnableEdit );
EnableWindow( pInfo->hwndPbConfigure, fEnableConfigure );
}
/*----------------------------------------------------------------------------
** Multi-link dialing dialog
** Listed alphabetically following stub API and dialog proc
**----------------------------------------------------------------------------
*/
BOOL
MultiLinkDialingDlg(
IN HWND hwndOwner,
OUT PBENTRY* pEntry )
/* Popup the Multi-link dialing dialog. 'HwndOwner' is the owner of the
** dialog. 'PEntry' is a phonebook entry to edit.
**
** Returns true if user pressed OK and succeeded, false if user pressed
** Cancel or encountered an error.
*/
{
int nStatus;
TRACE("MultiLinkConfigureDlg");
nStatus =
(BOOL )DialogBoxParam(
g_hinstDll,
MAKEINTRESOURCE( DID_DM_DialingMultipleLines ),
hwndOwner,
DmDlgProc,
(LPARAM )pEntry );
if (nStatus == -1)
{
ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
nStatus = FALSE;
}
return (BOOL )nStatus;
}
INT_PTR CALLBACK
DmDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam )
/* DialogProc callback for the Multi-Link dialing dialog. Parameters and
** return value are as described for standard windows 'DialogProc's.
*/
{
#if 0
TRACE4("DmDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
(DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
#endif
switch (unMsg)
{
case WM_INITDIALOG:
return DmInit( hwnd, (PBENTRY* )lparam );
case WM_HELP:
case WM_CONTEXTMENU:
ContextHelp( g_adwDmHelp, hwnd, unMsg, wparam, lparam );
break;
case WM_COMMAND:
{
return DmCommand(
hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
}
case WM_DESTROY:
{
DmTerm( hwnd );
break;
}
}
return FALSE;
}
BOOL
DmCommand(
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;
TRACE2("DmCommand(n=%d,i=%d)",
(DWORD)wNotification,(DWORD)wId);
switch (wId)
{
case CID_DM_RB_DialAll:
case CID_DM_RB_DialAsNeeded:
{
DMINFO* pInfo = (DMINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
DmUpdateAsNeededState( pInfo );
break;
}
case IDOK:
{
DMINFO* pInfo;
TRACE("OK pressed");
pInfo = (DMINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
ASSERT(pInfo);
DmSave( pInfo );
EndDialog( hwnd, TRUE );
return TRUE;
}
case IDCANCEL:
{
TRACE("Cancel pressed");
EndDialog( hwnd, FALSE );
return TRUE;
}
}
return FALSE;
}
BOOL
DmInit(
IN HWND hwndDlg,
IN PBENTRY* pEntry )
/* Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
** 'PEntry' is the caller's stub API argument.
**
** Return false if focus was set, true otherwise, i.e. as defined for
** WM_INITDIALOG.
*/
{
DWORD dwErr;
DMINFO* pInfo;
TRACE("DmInit");
/* 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->pEntry = pEntry;
pInfo->hwndDlg = hwndDlg;
SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo );
TRACE("Context set");
}
pInfo->hwndRbDialAll = GetDlgItem( hwndDlg, CID_DM_RB_DialAll );
ASSERT(pInfo->hwndRbDialAll);
pInfo->hwndRbDialAsNeeded = GetDlgItem( hwndDlg, CID_DM_RB_DialAsNeeded );
ASSERT(pInfo->hwndRbDialAsNeeded);
pInfo->hwndStDial = GetDlgItem( hwndDlg, CID_DM_ST_Dial );
ASSERT(pInfo->hwndStDial);
pInfo->hwndLbDialPercent = GetDlgItem( hwndDlg, CID_DM_LB_DialPercent );
ASSERT(pInfo->hwndLbDialPercent);
pInfo->hwndStDialOrMore = GetDlgItem( hwndDlg, CID_DM_ST_DialOrMore );
ASSERT(pInfo->hwndStDialOrMore);
pInfo->hwndEbDialMinutes = GetDlgItem( hwndDlg, CID_DM_EB_DialMinutes );
ASSERT(pInfo->hwndEbDialMinutes);
pInfo->hwndStDialMinutes = GetDlgItem( hwndDlg, CID_DM_ST_DialMinutes );
ASSERT(pInfo->hwndStDialMinutes);
pInfo->hwndStHangUp = GetDlgItem( hwndDlg, CID_DM_ST_HangUp );
ASSERT(pInfo->hwndStHangUp);
pInfo->hwndLbHangUpPercent = GetDlgItem( hwndDlg, CID_DM_LB_HangUpPercent );
ASSERT(pInfo->hwndLbHangUpPercent);
pInfo->hwndStHangUpOrLess = GetDlgItem( hwndDlg, CID_DM_ST_HangUpOrLess );
ASSERT(pInfo->hwndStHangUpOrLess);
pInfo->hwndEbHangUpMinutes = GetDlgItem( hwndDlg, CID_DM_EB_HangUpMinutes );
ASSERT(pInfo->hwndEbHangUpMinutes);
pInfo->hwndStHangUpMinutes = GetDlgItem( hwndDlg, CID_DM_ST_HangUpMinutes );
ASSERT(pInfo->hwndStHangUpMinutes);
/* Install the spin-button controls and initialize the edit fields.
*/
{
HWND hwndUdDialMinutes;
HWND hwndUdHangUpMinutes;
hwndUdDialMinutes = CreateUpDownControl(
WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT +
UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS,
0, 0, 0, 0, hwndDlg, 100, g_hinstDll, pInfo->hwndEbDialMinutes,
UD_MAXVAL, 0, 0 );
ASSERT(hwndUdDialMinutes);
Edit_LimitText( pInfo->hwndEbDialMinutes, 7 );
SetDlgItemInt( hwndDlg, CID_DM_EB_DialMinutes,
pEntry->dwDialSeconds / 60, FALSE );
hwndUdHangUpMinutes = CreateUpDownControl(
WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT +
UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS,
0, 0, 0, 0, hwndDlg, 101, g_hinstDll, pInfo->hwndEbHangUpMinutes,
UD_MAXVAL, 0, 0 );
ASSERT(hwndUdHangUpMinutes);
Edit_LimitText( pInfo->hwndEbHangUpMinutes, 7 );
SetDlgItemInt( hwndDlg, CID_DM_EB_HangUpMinutes,
pEntry->dwHangUpSeconds / 60, FALSE );
}
/* Initialize the drop lists.
*/
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("0%"), (VOID* )0 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("10%"), (VOID* )10 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("20%"), (VOID* )20 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("30%"), (VOID* )30 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("40%"), (VOID* )40 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("50%"), (VOID* )50 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("60%"), (VOID* )60 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("70%"), (VOID* )70 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("80%"), (VOID* )80 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("90%"), (VOID* )90 );
ComboBox_AddItem( pInfo->hwndLbDialPercent, TEXT("100%"), (VOID* )100 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("0%"), (VOID* )0 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("10%"), (VOID* )10 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("20%"), (VOID* )20 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("30%"), (VOID* )30 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("40%"), (VOID* )40 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("50%"), (VOID* )50 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("60%"), (VOID* )60 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("70%"), (VOID* )70 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("80%"), (VOID* )80 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("90%"), (VOID* )90 );
ComboBox_AddItem( pInfo->hwndLbHangUpPercent, TEXT("100%"), (VOID* )100 );
ComboBox_SetCurSel( pInfo->hwndLbDialPercent,
(min( pEntry->dwDialPercent, 100 )) / 10 );
ComboBox_SetCurSel( pInfo->hwndLbHangUpPercent,
(min( pEntry->dwHangUpPercent, 100 )) / 10 );
/* Set the radio button selection, triggering appropriate
** enabling/disabling.
*/
{
HWND hwndRb;
if (pEntry->dwDialMode = RASEDM_DialAll)
hwndRb = pInfo->hwndRbDialAll;
else
hwndRb = pInfo->hwndRbDialAsNeeded;
SendMessage( hwndRb, BM_CLICK, 0, 0 );
}
/* Center dialog 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
DmSave(
IN DMINFO* pInfo )
/* Save the current dialog state in the stub API entry buffer. 'PInfo' is
** the dialog context.
*/
{
UINT unValue;
BOOL f;
TRACE("DmSave");
if (Button_GetCheck( pInfo->hwndRbDialAll ))
pInfo->pEntry->dwDialMode = RASEDM_DialAll;
else
pInfo->pEntry->dwDialMode = RASEDM_DialAsNeeded;
pInfo->pEntry->dwDialPercent = (DWORD)
ComboBox_GetItemData( pInfo->hwndLbDialPercent,
ComboBox_GetCurSel( pInfo->hwndLbDialPercent ) );
unValue = GetDlgItemInt(
pInfo->hwndDlg, CID_DM_EB_DialMinutes, &f, FALSE );
if (f && unValue <= 9999999)
pInfo->pEntry->dwDialSeconds = (DWORD )unValue * 60;
pInfo->pEntry->dwHangUpPercent = (DWORD)
ComboBox_GetItemData( pInfo->hwndLbHangUpPercent,
ComboBox_GetCurSel( pInfo->hwndLbHangUpPercent ) );
unValue = GetDlgItemInt(
pInfo->hwndDlg, CID_DM_EB_HangUpMinutes, &f, FALSE );
if (f && unValue <= 9999999)
pInfo->pEntry->dwHangUpSeconds = (DWORD )unValue * 60;
pInfo->pEntry->fDirty = TRUE;
}
VOID
DmTerm(
IN HWND hwndDlg )
/* Dialog termination. Releases the context block. 'HwndDlg' is the
** handle of a dialog.
*/
{
DMINFO* pInfo;
TRACE("DmTerm");
pInfo = (DMINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
if (pInfo)
{
Free( pInfo );
TRACE("Context freed");
}
}
VOID
DmUpdateAsNeededState(
IN DMINFO* pInfo )
/* Enable/disable "as needed" controls based on radio button selection.
** 'PInfo' is the dialog context.
*/
{
BOOL f;
TRACE("DmUpdateAsNeededState");
f = Button_GetCheck( pInfo->hwndRbDialAsNeeded );
EnableWindow( pInfo->hwndStDial, f );
EnableWindow( pInfo->hwndLbDialPercent, f );
EnableWindow( pInfo->hwndStDialOrMore, f );
EnableWindow( pInfo->hwndEbDialMinutes, f );
EnableWindow( pInfo->hwndStDialMinutes, f );
EnableWindow( pInfo->hwndStHangUp, f );
EnableWindow( pInfo->hwndLbHangUpPercent, f );
EnableWindow( pInfo->hwndStHangUpOrLess, f );
EnableWindow( pInfo->hwndEbHangUpMinutes, f );
EnableWindow( pInfo->hwndStHangUpMinutes, f );
}