/* Copyright (c) 1995, Microsoft Corporation, all rights reserved ** ** entryps.c ** Remote Access Common Dialog APIs ** Phonebook Entry property sheet ** ** 06/20/95 Steve Cobb */ #include "rasdlgp.h" // Our private header #define INCL_ENCRYPT #include // For IsEncryptionPermitted() #include "entry.h" // Shared with add entry wizard #define RASMERGE /* Page definitions. */ #define PE_BsPage 0 #define PE_SvPage 1 #define PE_ScPage 2 #define PE_SePage 3 #define PE_XsPage 4 #define PE_RdPage 5 #define PE_PageCount 6 #define PE_PageCountNoRtr 5 /*---------------------------------------------------------------------------- ** Help maps **---------------------------------------------------------------------------- */ static DWORD g_adwBsHelp[] = { CID_BS_ST_EntryName, HID_BS_EB_EntryName, CID_BS_EB_EntryName, HID_BS_EB_EntryName, CID_BS_ST_Description, HID_BS_EB_Description, CID_BS_EB_Description, HID_BS_EB_Description, CID_BS_ST_CountryCode, HID_BS_LB_CountryCode, CID_BS_LB_CountryCode, HID_BS_LB_CountryCode, CID_BS_ST_AreaCode, HID_BS_CL_AreaCode, CID_BS_CL_AreaCode, HID_BS_CL_AreaCode, CID_BS_ST_PhoneNumber, HID_BS_EB_PhoneNumber, CID_BS_EB_PhoneNumber, HID_BS_EB_PhoneNumber, CID_BS_PB_Alternates, HID_BS_PB_Alternates, CID_BS_ST_Device, HID_BS_LB_Device, CID_BS_LB_Device, HID_BS_LB_Device, CID_BS_PB_Configure, HID_BS_PB_Configure, CID_BS_CB_UseAreaCountryCodes, HID_BS_CB_UseAreaCountryCodes, CID_BS_CB_UseOtherPort, HID_BS_CB_UseOtherPort, 0, 0 }; static DWORD g_adwSvHelp[] = { CID_SV_ST_ServerType, HID_SV_LB_ServerType, CID_SV_LB_ServerType, HID_SV_LB_ServerType, CID_SV_GB_Protocols, HID_SV_GB_Protocols, CID_SV_CB_TcpIp, HID_SV_CB_TcpIp, CID_SV_CB_Ipx, HID_SV_CB_Ipx, CID_SV_CB_Netbeui, HID_SV_CB_Netbeui, CID_SV_PB_TcpIpSettings, HID_SV_PB_TcpIpSettings, CID_SV_CB_SwCompression, HID_SV_CB_SwCompression, CID_SV_CB_LcpExtensions, HID_SV_CB_LcpExtensions, 0, 0 }; static DWORD g_adwScHelp[] = { CID_SC_RB_None, HID_SC_RB_None, CID_SC_RB_Terminal, HID_SC_RB_Terminal, CID_SC_RB_Script, HID_SC_RB_Script, CID_SC_LB_Script, HID_SC_LB_Script, CID_SC_PB_Edit, HID_SC_PB_Edit, CID_SC_PB_Refresh, HID_SC_PB_Refresh, CID_SC_PB_Before, HID_SC_PB_BeforeDial, 0, 0 }; static DWORD g_adwSeHelp[] = { CID_SE_GB_AuthEncryption, HID_SE_GB_AuthEncryption, CID_SE_RB_AnyAuth, HID_SE_RB_AnyAuth, CID_SE_RB_EncryptedAuth, HID_SE_RB_EncryptedAuth, CID_SE_RB_MsEncryptedAuth, HID_SE_RB_MsEncryptedAuth, CID_SE_CB_UseLogonCredentials, HID_SE_CB_UseLogonCredentials, CID_SE_CB_RequireDataEncryption, HID_SE_CB_RequireDataEncryption, CID_SE_CB_RequireStrongDataEncryption, HID_SE_CB_RequireStrongDataEncryption, CID_SE_PB_UnsavePw, HID_SE_PB_UnsavePw, CID_SE_CB_AuthenticateServer, HID_SE_CB_AuthenticateServer, 0, 0 }; static DWORD g_adwXsHelp[] = { CID_XS_ST_Network, HID_XS_LB_Network, CID_XS_LB_Network, HID_XS_LB_Network, CID_XS_ST_Address, HID_XS_EB_Address, CID_XS_EB_Address, HID_XS_EB_Address, CID_XS_GB_Optional, HID_XS_GB_Optional, CID_XS_ST_UserData, HID_XS_EB_UserData, CID_XS_EB_UserData, HID_XS_EB_UserData, CID_XS_ST_Facilities, HID_XS_EB_Facilities, CID_XS_EB_Facilities, HID_XS_EB_Facilities, 0, 0 }; static DWORD g_adwBdHelp[] = { CID_BD_RB_None, HID_BD_RB_None, CID_BD_RB_Terminal, HID_BD_RB_Terminal, CID_BD_RB_Script, HID_BD_RB_Script, CID_BD_LB_Script, HID_BD_LB_Script, CID_BD_PB_Edit, HID_BD_PB_Edit, CID_BD_PB_Refresh, HID_BD_PB_Refresh, 0, 0 }; static DWORD g_adwRdHelp[] = { CID_RD_RB_Persistent, HID_RD_RB_Persistent, CID_RD_RB_DemandDial, HID_RD_RB_DemandDial, CID_RD_ST_Attempts, HID_RD_EB_Attempts, CID_RD_EB_Attempts, HID_RD_EB_Attempts, CID_RD_ST_Seconds, HID_RD_EB_Seconds, CID_RD_EB_Seconds, HID_RD_EB_Seconds, CID_RD_ST_Idle, HID_RD_EB_Idle, CID_RD_EB_Idle, HID_RD_EB_Idle, CID_RD_PB_Callback, HID_RD_PB_Callback, CID_RD_PB_MultipleLines, HID_RD_PB_MultipleLines, 0, 0 }; static DWORD g_adwCrHelp[] = { CID_CR_RB_No, HID_CR_RB_No, CID_CR_RB_Yes, HID_CR_RB_Yes, CID_CR_ST_Numbers, HID_CR_LV_Numbers, CID_CR_LV_Numbers, HID_CR_LV_Numbers, CID_CR_PB_Edit, HID_CR_PB_Edit, CID_CR_PB_Delete, HID_CR_PB_Delete, 0, 0 }; /*---------------------------------------------------------------------------- ** Local datatypes (alphabetically) **---------------------------------------------------------------------------- */ /* Phonebook Entry property sheet context block. All property pages refer to ** the single context block is associated with the sheet. */ #define PEINFO struct tagPEINFO PEINFO { /* Common input arguments. */ EINFO* pArgs; /* Property sheet dialog and property page handles. 'hwndFirstPage' is ** the handle of the first property page initialized. This is the page ** that allocates and frees the context block. */ HWND hwndDlg; HWND hwndFirstPage; HWND hwndBs; HWND hwndSv; HWND hwndSc; HWND hwndSe; HWND hwndXs; HWND hwndRd; /* Basic page. */ HWND hwndEbEntryName; HWND hwndEbDescription; HWND hwndStCountryCode; HWND hwndLbCountryCodes; HWND hwndStAreaCode; HWND hwndLbAreaCodes; HWND hwndStPhoneNumber; HWND hwndEbPhoneNumber; HWND hwndPbAlternate; HWND hwndStDevice; HWND hwndLbDevices; HWND hwndPbConfigure; HWND hwndCbUseAreaCode; HWND hwndCbUseOtherPort; POINT xyStPhoneNumber; POINT xyEbPhoneNumber; POINT xyPbAlternate; POINT xyStDevice; POINT xyLbDevice; POINT xyPbConfigure; POINT xyCbUseAreaCode; POINT xyCbUseOtherPort; int dyAreaCodeAdjust; /* Server page. */ HWND hwndStServerTypes; HWND hwndLbServerTypes; HWND hwndCbIp; HWND hwndPbIp; HWND hwndCbIpx; HWND hwndCbNbf; HWND hwndCbSwCompression; HWND hwndCbLcpExtensions; DWORD dwfInstalledProtocols; DWORD dwBaseProtocolDefault; BOOL fPppIp; BOOL fPppIpx; BOOL fPppNbf; BOOL fPppIpDefault; BOOL fPppIpxDefault; BOOL fPppNbfDefault; BOOL fSwCompression; BOOL fLcpExtensions; /* Script page. */ HWND hwndRbNone; HWND hwndRbTerminal; HWND hwndRbScript; HWND hwndLbScript; HWND hwndPbEdit; HWND hwndPbRefresh; /* Security page. */ HWND hwndRbAnyAuth; HWND hwndRbEncryptedAuth; HWND hwndRbMsEncryptedAuth; HWND hwndCbDataEncryption; HWND hwndCbStrongDataEncryption; HWND hwndCbUseLogon; HWND hwndCbAuthenticateServer; HWND hwndCbSecureFiles; HWND hwndPbUnsavePw; BOOL fEncryptionPermitted; BOOL fDataEncryption; BOOL fStrongDataEncryption; BOOL fUseLogon; /* X.25 page. */ HWND hwndLbX25Pads; HWND hwndEbX25Address; HWND hwndEbX25UserData; HWND hwndEbX25Facilities; /* (Router) Dialing page. */ HWND hwndRbPersistent; HWND hwndRbDemand; HWND hwndStAttempts; HWND hwndEbAttempts; HWND hwndStSeconds; HWND hwndEbSeconds; HWND hwndStIdle; HWND hwndEbIdle; /* List of PADs initialized by XsFillPadsList, if necessary, and freed by ** PeTerm. */ DTLLIST* pListPads; /* The phone number stash for single link mode. This allows user to ** change the port to another link without losing the phone number he ** typed. */ DTLLIST* pListPhoneNumbers; BOOL fPromoteHuntNumbers; /* The current device list selection index. Used to back out change from ** multi-line mode to single line mode if user is just screwing with ** device list box. Initialized by PeInit. */ INT iLbDevices; /* True if Multiple Lines is selected, false otherwise. Does not ** necessarily mean there is currently more than one PBLINK. Initialized ** by PeInit. */ BOOL fMultiLinkMode; /* The current server type list selection index. Used to back out change ** if user changes to non-PPP with Multiple Lines selected. Initialized ** by PeInit. */ INT iLbServerTypes; /* The address of the first link and the associated PBPORT, maintained for ** convenience. Initialized by PeInit. */ PBLINK* pLink; PBPORT* pPort; /* Our per-entry version of the "any port" flag stored per-link in the ** phonebook. Initialized by BsInit. */ BOOL fOtherPortOk; }; /* Before Dial dialog context block. */ #define BDINFO struct tagBDINFO BDINFO { /* Caller's argument to the stub API. */ EINFO* pArgs; /* Dialog and control handles. */ HWND hwndDlg; HWND hwndRbNone; HWND hwndRbTerminal; HWND hwndRbScript; HWND hwndLbScript; HWND hwndPbEdit; HWND hwndPbRefresh; }; /* (Router) Callback context block. */ #define CRINFO struct tagCRINFO CRINFO { /* Caller's argument to the stub API. */ EINFO* pArgs; /* Dialog and control handles. */ HWND hwndDlg; HWND hwndRbNo; HWND hwndRbYes; HWND hwndLvNumbers; HWND hwndPbEdit; HWND hwndPbDelete; }; /*---------------------------------------------------------------------------- ** Local prototypes (alphabetically) **---------------------------------------------------------------------------- */ INT_PTR CALLBACK BdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL BdCommand( IN BDINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); BOOL BdInit( IN HWND hwndDlg, IN EINFO* pArgs ); VOID BdSave( IN BDINFO* pInfo ); VOID BdTerm( IN HWND hwndDlg ); BOOL BeforeDialDlg( IN HWND hwndOwner, IN OUT EINFO* pEinfo ); INT_PTR CALLBACK BsDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL BsCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); VOID BsConfigure( IN PEINFO* pInfo ); VOID BsFillDeviceList( IN PEINFO* pInfo ); BOOL BsInit( IN HWND hwndPage, IN OUT EINFO* pArgs ); VOID BsLbDevicesSelChange( IN PEINFO* pInfo ); VOID BsPhoneNumberToStash( IN PEINFO* pInfo ); VOID BsUpdateAreaAndCountryCode( IN PEINFO* pInfo ); INT_PTR CALLBACK CrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL CrCommand( IN CRINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); BOOL CrInit( IN HWND hwndDlg, IN EINFO* pArgs ); VOID CrSave( IN CRINFO* pInfo ); VOID CrTerm( IN HWND hwndDlg ); VOID CrUpdateLvAndPbState( IN CRINFO* pInfo ); INT_PTR CALLBACK RdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL RdCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); BOOL RdInit( IN HWND hwndPage ); BOOL PeApply( IN HWND hwndPage ); VOID PeCancel( IN HWND hwndPage ); PEINFO* PeContext( IN HWND hwndPage ); DWORD PeCountEnabledLinks( IN PEINFO* pInfo ); VOID PeExit( IN PEINFO* pInfo, IN DWORD dwError ); VOID PeExitInit( IN HWND hwndDlg ); PEINFO* PeInit( IN HWND hwndFirstPage, IN EINFO* pArgs ); VOID PeTerm( IN HWND hwndPage ); VOID PeUpdateShortcuts( IN PEINFO* pInfo ); BOOL RouterCallbackDlg( IN HWND hwndOwner, IN OUT EINFO* pEinfo ); BOOL ScCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK ScDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL ScInit( IN HWND hwndPage ); BOOL SeCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK SeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL SeInit( IN HWND hwndPage ); VOID SvCbIpClicked( IN PEINFO* pInfo ); VOID SvCbIpxClicked( IN PEINFO* pInfo ); VOID SvCbNbfClicked( IN PEINFO* pInfo ); BOOL SvCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK SvDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL SvInit( IN HWND hwndPage ); VOID SvLbServerTypesSelChange( IN PEINFO* pInfo ); VOID SvProtocolNotInstalledPopup( IN PEINFO* pInfo, IN DWORD dwSid ); VOID SvTcpipSettings( IN PEINFO* pInfo ); INT_PTR CALLBACK XsDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); VOID XsFillPadsList( IN PEINFO* pInfo, IN BOOL fLocalPad ); BOOL XsInit( IN HWND hwndPage ); /*---------------------------------------------------------------------------- ** Callback utility prototypes (alphabetically) **---------------------------------------------------------------------------- */ VOID CbutilDelete( IN HWND hwndDlg, IN HWND hwndLvNumbers ); VOID CbutilEdit( IN HWND hwndDlg, IN HWND hwndLvNumbers ); VOID CbutilFillLvNumbers( IN HWND hwndDlg, IN HWND hwndLvNumbers, IN DTLLIST* pListCallback, IN BOOL fRouter ); LVXDRAWINFO* CbutilLvNumbersCallback( IN HWND hwndLv, IN DWORD dwItem ); VOID CbutilSaveLv( IN HWND hwndLvNumbers, OUT DTLLIST* pListCallback ); /*---------------------------------------------------------------------------- ** Phonebook Entry property sheet entry point **---------------------------------------------------------------------------- */ VOID PePropertySheet( IN OUT EINFO* pEinfo ) /* Runs the Phonebook entry property sheet. 'PEinfo' is the API caller's ** arguments. */ { DWORD dwErr; PROPSHEETHEADER header; PROPSHEETPAGE apage[ PE_PageCount ]; PROPSHEETPAGE* ppage; TCHAR* pszTitle; TRACE("PePropertySheet"); if (pEinfo->pApiArgs->dwFlags & RASEDFLAG_NewEntry) pszTitle = PszFromId( g_hinstDll, SID_PeTitleNew ); else if (pEinfo->pApiArgs->dwFlags & RASEDFLAG_CloneEntry) pszTitle = PszFromId( g_hinstDll, SID_PeTitleClone ); else pszTitle = PszFromId( g_hinstDll, SID_PeTitleEdit ); ZeroMemory( &header, sizeof(header) ); header.dwSize = sizeof(PROPSHEETHEADER); header.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_USECALLBACK; header.hwndParent = pEinfo->pApiArgs->hwndOwner; header.hInstance = g_hinstDll; header.pszCaption = (pszTitle) ? pszTitle : L""; header.nPages = (pEinfo->fRouter) ? PE_PageCount : PE_PageCountNoRtr; header.ppsp = apage; header.pfnCallback = UnHelpCallbackFunc; ZeroMemory( apage, sizeof(apage) ); ppage = &apage[ PE_BsPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (pEinfo->fRouter) ? MAKEINTRESOURCE( PID_BS_RouterBasicSettings ) : MAKEINTRESOURCE( PID_BS_BasicSettings ); ppage->pfnDlgProc = BsDlgProc; ppage->lParam = (LPARAM )pEinfo; ppage = &apage[ PE_SvPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (pEinfo->fRouter) ? MAKEINTRESOURCE( PID_SV_RouterServerSettings ) : MAKEINTRESOURCE( PID_SV_ServerSettings ); ppage->pfnDlgProc = SvDlgProc; ppage = &apage[ PE_ScPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (pEinfo->fRouter) ? MAKEINTRESOURCE( PID_SC_RouterScriptSettings ) : MAKEINTRESOURCE( PID_SC_ScriptSettings ); ppage->pfnDlgProc = ScDlgProc; ppage = &apage[ PE_SePage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (pEinfo->fRouter) ? MAKEINTRESOURCE( PID_SE_RouterSecuritySettings ) : MAKEINTRESOURCE( PID_SE_SecuritySettings ); ppage->pfnDlgProc = SeDlgProc; ppage = &apage[ PE_XsPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = MAKEINTRESOURCE( PID_XS_X25Settings ); ppage->pfnDlgProc = XsDlgProc; if (pEinfo->fRouter) { ppage = &apage[ PE_RdPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = MAKEINTRESOURCE( PID_RD_Dialing ); ppage->pfnDlgProc = RdDlgProc; } if (PropertySheet( &header ) == -1) { TRACE("PropertySheet failed"); ErrorDlg( pEinfo->pApiArgs->hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); } Free0( pszTitle ); } /*---------------------------------------------------------------------------- ** Phonebook Entry property sheet ** Listed alphabetically **---------------------------------------------------------------------------- */ BOOL PeApply( IN HWND hwndPage ) /* Saves the contents of the property sheet. 'HwndPage is the handle of a ** property page. Pops up any errors that occur. ** ** Returns true is page can be dismissed, false otherwise. */ { DWORD dwErr; PEINFO* pInfo; PBENTRY* pEntry; BOOL fLocalPad; INT iPadSelection; TRACE("PeApply"); pInfo = PeContext( hwndPage ); ASSERT(pInfo); pEntry = pInfo->pArgs->pEntry; ASSERT(pEntry); iPadSelection = 0; fLocalPad = IsLocalPad( pEntry ); if (fLocalPad) { /* Can't have a dialup-PAD network defined when the selected device is ** a PAD card. */ Free0( pEntry->pszX25Network ); pEntry->pszX25Network = NULL; } /* First page should always be initialized. */ ASSERT(pInfo->hwndBs); Free0( pEntry->pszEntryName ); pEntry->pszEntryName = GetText( pInfo->hwndEbEntryName ); Free0( pEntry->pszDescription ); pEntry->pszDescription = GetText( pInfo->hwndEbDescription ); Free0( pEntry->pszAreaCode ); pEntry->pszAreaCode = GetText( pInfo->hwndLbAreaCodes ); if (!pEntry->pszEntryName || !pEntry->pszAreaCode) { dwErr = ERROR_NOT_ENOUGH_MEMORY; ErrorDlg( pInfo->hwndDlg, SID_OP_RetrievingData, dwErr, NULL ); PeExit( pInfo, dwErr ); return TRUE; } /* Save stashed phone number settings in single link. */ if (!pInfo->fMultiLinkMode) { BsPhoneNumberToStash( pInfo ); EuPhoneNumberStashToEntry( pInfo->pArgs, pInfo->pListPhoneNumbers, pInfo->fPromoteHuntNumbers, FALSE ); } pEntry->fUseCountryAndAreaCode = IsDlgButtonChecked( pInfo->hwndBs, CID_BS_CB_UseAreaCountryCodes ); EuSaveCountryInfo( pInfo->pArgs, pInfo->hwndLbCountryCodes ); /* Retrieve the current "any port" flag which is displayed per-entry, ** though stored per-link. ** ** Most link/port information is saved as they are changed, since these ** settings are changed on a sub-dialog. However, this setting and a few ** other consistency adjustments are made in a loop below. */ pInfo->fOtherPortOk = IsDlgButtonChecked( pInfo->hwndBs, CID_BS_CB_UseOtherPort ); /* Server page. */ if (pInfo->hwndSv) { BOOL fChange = FALSE; BOOL fDeselect = FALSE; /* Note: pEntry->dwBaseProtocol is saved as changed. */ /* Warn SLIP framing won't work without IP installed. */ if (pEntry->dwBaseProtocol == BP_Slip && !(pInfo->dwfInstalledProtocols & NP_Ip)) { MsgDlg( pInfo->hwndSv, SID_SlipWithoutIp, NULL ); } #ifdef AMB /* Warn RAS framing won't work without NetBEUI installed. */ if (pEntry->dwBaseProtocol == BP_Ras && !(pInfo->dwfInstalledProtocols & NP_Nbf)) { MsgDlg( pInfo->hwndSv, SID_RasWithoutNbf, NULL ); } #endif if (pEntry->dwBaseProtocol == BP_Ppp) { DWORD dwfExcludedProtocols = pEntry->dwfExcludedProtocols; if (pInfo->fPppIp && !pInfo->fPppIpDefault) { dwfExcludedProtocols &= ~(NP_Ip); fChange = TRUE; } else if (!pInfo->fPppIp && pInfo->fPppIpDefault) { dwfExcludedProtocols |= NP_Ip; fChange = TRUE; fDeselect = TRUE; } if (pInfo->fPppIpx && !pInfo->fPppIpxDefault) { dwfExcludedProtocols &= ~(NP_Ipx); fChange = TRUE; } else if (!pInfo->fPppIpx && pInfo->fPppIpxDefault) { dwfExcludedProtocols |= NP_Ipx; fChange = TRUE; fDeselect = TRUE; } if (pInfo->fPppNbf && !pInfo->fPppNbfDefault) { dwfExcludedProtocols &= ~(NP_Nbf); fChange = TRUE; } else if (!pInfo->fPppNbf && pInfo->fPppNbfDefault) { dwfExcludedProtocols |= NP_Nbf; fChange = TRUE; } /* Warn PPP won't work without a network protocol. */ if ((pInfo->dwfInstalledProtocols & ~(dwfExcludedProtocols)) == 0) { if (pInfo->dwfInstalledProtocols) { MsgDlg( pInfo->hwndSv, SID_PppNeedsProtocol, NULL ); PropSheet_SetCurSel( pInfo->hwndDlg, NULL, PE_SvPage ); SetFocus( pInfo->hwndCbIp ); return FALSE; } else { MsgDlg( pInfo->hwndSv, SID_PppWithoutProtocol, NULL ); } } /* In the case of demand-dial router interfaces, ** deselecting a CP removes the corresponding router-manager ** and routing-protocols. Warn the user about this. */ if (pInfo->pArgs->fRouter && !(pInfo->pArgs->pApiArgs->dwFlags & RASEDFLAG_NewEntry) && fDeselect) { MSGARGS msgargs; ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION; if (MsgDlg( pInfo->hwndSv, SID_RemoveCP, &msgargs ) != IDYES) { PropSheet_SetCurSel(pInfo->hwndDlg, NULL, PE_SvPage); SetFocus(pInfo->hwndCbIp); return FALSE; } } pEntry->dwfExcludedProtocols = dwfExcludedProtocols; } if (pEntry->dwBaseProtocol != pInfo->dwBaseProtocolDefault) fChange = TRUE; if (fChange) pEntry->dwAuthentication = (DWORD )-1; pEntry->fSwCompression = pInfo->fSwCompression; pEntry->fLcpExtensions = pInfo->fLcpExtensions; } /* Script page. */ if (pInfo->hwndSc) { TCHAR* psz; if (IsDlgButtonChecked( pInfo->hwndSc, CID_SC_RB_None )) pEntry->dwScriptModeAfter = SM_None; else if (IsDlgButtonChecked( pInfo->hwndSc, CID_SC_RB_Terminal )) pEntry->dwScriptModeAfter = SM_Terminal; else pEntry->dwScriptModeAfter = SM_Script; psz = GetText( pInfo->hwndLbScript ); Free0( pEntry->pszScriptAfter ); pEntry->pszScriptAfter = psz; /* Silently fix-up "no script specified" error. */ if (pEntry->dwScriptModeAfter == SM_Script && !pEntry->pszScriptAfter) pEntry->dwScriptModeAfter = SM_None; } /* Security page. */ if (pInfo->hwndSe) { if (Button_GetCheck( pInfo->hwndRbAnyAuth )) pEntry->dwAuthRestrictions = AR_AuthAny; else if (Button_GetCheck( pInfo->hwndRbEncryptedAuth )) pEntry->dwAuthRestrictions = AR_AuthEncrypted; else pEntry->dwAuthRestrictions = AR_AuthMsEncrypted; if (pInfo->fStrongDataEncryption) pEntry->dwDataEncryption = DE_Strong; else if (pInfo->fDataEncryption) pEntry->dwDataEncryption = DE_Weak; else pEntry->dwDataEncryption = DE_None; pEntry->fAutoLogon = pInfo->fUseLogon; pEntry->fSecureLocalFiles = Button_GetCheck( pInfo->hwndCbSecureFiles ); if (pInfo->pArgs->fRouter) { pEntry->fAuthenticateServer = Button_GetCheck( pInfo->hwndCbAuthenticateServer ); } } /* X.25 page. */ if (pInfo->hwndXs) { iPadSelection = ComboBox_GetCurSel( pInfo->hwndLbX25Pads ); Free0( pEntry->pszX25Network ); if (iPadSelection > 0) pEntry->pszX25Network = GetText( pInfo->hwndLbX25Pads ); else pEntry->pszX25Network = NULL; Free0( pEntry->pszX25Address ); pEntry->pszX25Address = GetText( pInfo->hwndEbX25Address ); Free0( pEntry->pszX25UserData ); pEntry->pszX25UserData = GetText( pInfo->hwndEbX25UserData ); Free0( pEntry->pszX25Facilities ); pEntry->pszX25Facilities = GetText( pInfo->hwndEbX25Facilities ); if (!pEntry->pszX25Address || !pEntry->pszX25UserData || !pEntry->pszX25Facilities) { Free0( pEntry->pszX25Address ); Free0( pEntry->pszX25UserData ); dwErr = ERROR_NOT_ENOUGH_MEMORY; ErrorDlg( pInfo->hwndDlg, SID_OP_RetrievingData, dwErr, NULL ); PeExit( pInfo, dwErr ); return TRUE; } } /* (Router) Dialing page. */ if (pInfo->hwndRd) { UINT unValue; BOOL f; unValue = GetDlgItemInt( pInfo->hwndRd, CID_RD_EB_Attempts, &f, FALSE ); if (f && unValue <= 999999999) pEntry->dwRedialAttempts = unValue; unValue = GetDlgItemInt( pInfo->hwndRd, CID_RD_EB_Seconds, &f, FALSE ); if (f && unValue <= 999999999) pEntry->dwRedialSeconds = unValue; unValue = GetDlgItemInt( pInfo->hwndRd, CID_RD_EB_Idle, &f, FALSE ); if (f && unValue <= 999999999) pEntry->dwIdleDisconnectSeconds = unValue; pEntry->fRedialOnLinkFailure = IsDlgButtonChecked( pInfo->hwndRd, CID_RD_RB_Persistent ); /* Mark the fields as overriding the global user preferences. */ pEntry->dwfOverridePref |= (RASOR_RedialAttempts | RASOR_RedialSeconds | RASOR_IdleDisconnectSeconds | RASOR_RedialOnLinkFailure); /* Note: Callback mode setting is saved on the CallbackRouter dialog. */ } /* Validate the entry name. */ if (!EuValidateName( pInfo->hwndDlg, pInfo->pArgs )) { PropSheet_SetCurSel( pInfo->hwndDlg, NULL, PE_BsPage ); SetFocus( pInfo->hwndEbEntryName ); Edit_SetSel( pInfo->hwndEbEntryName, 0, -1 ); return FALSE; } /* Validate area code. */ if (!EuValidateAreaCode( pInfo->hwndDlg, pInfo->pArgs )) { PropSheet_SetCurSel( pInfo->hwndDlg, NULL, PE_BsPage ); SetFocus( pInfo->hwndLbAreaCodes ); ComboBox_SetEditSel( pInfo->hwndLbAreaCodes, 0, -1 ); return FALSE; } if ((fLocalPad || iPadSelection != 0) && (!pEntry->pszX25Address || IsAllWhite( pEntry->pszX25Address ))) { /* Address field is blank with X.25 dial-up or local PAD chosen. */ MsgDlg( pInfo->hwndDlg, SID_NoX25Address, NULL ); PropSheet_SetCurSel( pInfo->hwndDlg, NULL, PE_XsPage ); SetFocus( pInfo->hwndEbX25Address ); Edit_SetSel( pInfo->hwndEbX25Address, 0, -1 ); return FALSE; } //!!! Check for non-SLIP on non-modem. /* Link chain updates: ** ** 1. Set 'fOtherPortOk' on each link to the setting for the entry. ** ** 2. Make sure proprietary ISDN options are disabled if more than one ** link is enabled. The proprietary ISDN option is only meaningful ** when calling a down-level server that needs Digiboard channel ** aggragation instead of PPP multi-link. */ { DTLNODE* pNode; DWORD cIsdnLinks; cIsdnLinks = 0; for (pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNode ); ASSERT(pLink); pLink->fOtherPortOk = pInfo->fOtherPortOk; if (pLink->fEnabled && pLink->pbport.pbdevicetype == PBDT_Isdn) ++cIsdnLinks; } if (cIsdnLinks > 1) { for (pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNode ); ASSERT(pLink); if (pLink->fEnabled && pLink->fProprietaryIsdn) pLink->fProprietaryIsdn = FALSE; } } } /* Inform user that edits to the connected entry won't take affect until ** the entry is hung up and re-dialed, per PierreS's insistence. */ if (HrasconnFromEntry( pInfo->pArgs->pFile->pszPath, pEntry->pszEntryName )) MsgDlg( pInfo->hwndDlg, SID_EditConnected, NULL ); /* It's a valid new/changed entry. Mark the entry for commitment. */ pInfo->pArgs->fCommit = TRUE; return TRUE; } VOID PeCancel( IN HWND hwndPage ) /* Cancel was pressed. 'HwndPage' is the handle of a property page. */ { TRACE("PeCancel"); } PEINFO* PeContext( IN HWND hwndPage ) /* Retrieve the property sheet context from a property page handle. */ { return (PEINFO* )GetProp( GetParent( hwndPage ), g_contextId ); } DWORD PeCountEnabledLinks( IN PEINFO* pInfo ) /* Returns the number of enabled links in the entry. */ { DWORD c; DTLNODE* pNode; c = 0; for (pNode = DtlGetFirstNode( pInfo->pArgs->pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNode ); if (pLink->fEnabled) ++c; } TRACE1("PeCountEnabledLinks=%d",c); return c; } VOID PeExit( IN PEINFO* pInfo, IN DWORD dwError ) /* Forces an exit from the dialog, reporting 'dwError' to the caller. ** 'PInfo' is the dialog context. ** ** Note: This cannot be called during initialization of the first page. ** See PeExitInit. */ { TRACE("PeExit"); pInfo->pArgs->pApiArgs->dwError = dwError; PropSheet_PressButton( pInfo->hwndDlg, PSBTN_CANCEL ); } VOID PeExitInit( IN HWND hwndDlg ) /* Utility to report errors within PeInit and other first page ** initialization. 'HwndDlg' is the dialog window. */ { SetOffDesktop( hwndDlg, SOD_MoveOff, NULL ); SetOffDesktop( hwndDlg, SOD_Free, NULL ); PostMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( IDCANCEL , BN_CLICKED ), (LPARAM )GetDlgItem( hwndDlg, IDCANCEL ) ); } PEINFO* PeInit( IN HWND hwndFirstPage, IN EINFO* pArgs ) /* Property sheet level initialization. 'HwndPage' is the handle of the ** first page. 'PArgs' is the common entry input argument block. ** ** Returns address of the context block if successful, NULL otherwise. If ** NULL is returned, an appropriate message has been displayed, and the ** property sheet has been cancelled. */ { DWORD dwErr; DWORD dwOp; PEINFO* pInfo; HWND hwndDlg = GetParent( hwndFirstPage ); TRACE("PeInit"); /* Allocate the context information block. Initialize it enough so that ** it can be destroyed properly, and associate the context with the ** window. */ { pInfo = Malloc( sizeof(*pInfo) ); if (!pInfo) { TRACE("Context NOT allocated"); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); pArgs->pApiArgs->dwError = ERROR_NOT_ENOUGH_MEMORY; PeExitInit( hwndDlg ); return NULL; } ZeroMemory( pInfo, sizeof(PEINFO) ); pInfo->pArgs = pArgs; pInfo->hwndDlg = hwndDlg; pInfo->hwndFirstPage = hwndFirstPage; pInfo->iLbDevices = -1; pInfo->iLbServerTypes = -1; if (!SetProp( hwndDlg, g_contextId, pInfo )) { TRACE("Context NOT set"); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); pArgs->pApiArgs->dwError = ERROR_UNKNOWN; Free( pInfo ); PeExitInit( hwndDlg ); return NULL; } TRACE("Context set"); } /* Position the dialog per API caller's instructions. */ PositionDlg( hwndDlg, pArgs->pApiArgs->dwFlags & RASDDFLAG_PositionDlg, pArgs->pApiArgs->xDlg, pArgs->pApiArgs->yDlg ); /* Mess with the title bar gadgets. */ TweakTitleBar( hwndDlg ); if (!pArgs->fChainPropertySheet) { // // Do not load RAS DLL entrypoints if we // have an RPC server set. // #ifdef RASMERGE if (!pArgs->fRouter) { #endif /* Load RAS DLL entrypoints which starts RASMAN, if necessary. */ dwErr = LoadRas( g_hinstDll, hwndDlg ); if (dwErr != 0) { ErrorDlg( hwndDlg, SID_OP_LoadRas, dwErr, NULL ); pArgs->pApiArgs->dwError = dwErr; PeExitInit( hwndDlg ); return NULL; } #ifdef RASMERGE } #endif /* Load the common entry information. This must happen after RasLoad, ** which must happen after the dialog has been positioned so that the ** "Waiting for services" appears where the dialog will eventually ** popup. Note that EuInit assumes that EuInit0 has previously been ** called. */ dwErr = EuInit( pArgs, &dwOp ); if (dwErr != 0) { ErrorDlg( hwndDlg, dwOp, dwErr, NULL ); pArgs->pApiArgs->dwError = dwErr; PeExitInit( hwndDlg ); return NULL; } } /* Stash phone number settings for first link. */ EuPhoneNumberStashFromEntry( pInfo->pArgs, &pInfo->pListPhoneNumbers, &pInfo->fPromoteHuntNumbers ); /* Initialize link related states and shortcut addresses. */ pInfo->fMultiLinkMode = (PeCountEnabledLinks( pInfo ) > 1); PeUpdateShortcuts( pInfo ); /* Set even fixed tab widths, per spec. */ SetEvenTabWidths( hwndDlg, (pArgs->fRouter) ? PE_PageCount : PE_PageCountNoRtr ); return pInfo; } VOID PeTerm( IN HWND hwndPage ) /* Property sheet level termination. Releases the context block. ** 'HwndPage' is the handle of a property page. */ { PEINFO* pInfo; TRACE("PeTerm"); pInfo = PeContext( hwndPage ); if (pInfo) { if (pInfo->pListPads) DtlDestroyList( pInfo->pListPads, DestroyPszNode ); Free( pInfo ); TRACE("Context freed"); } RemoveProp( GetParent( hwndPage ), g_contextId ); } VOID PeUpdateShortcuts( IN PEINFO* pInfo ) /* Update first link and port shortcut pointers. */ { DTLNODE* pNode; TRACE("PeUpdateShortcuts"); pNode = DtlGetFirstNode( pInfo->pArgs->pEntry->pdtllistLinks ); ASSERT(pNode); pInfo->pLink = (PBLINK* )DtlGetData( pNode ); ASSERT(pInfo->pLink); pInfo->pPort = &pInfo->pLink->pbport; } /*---------------------------------------------------------------------------- ** Basic property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK BsDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Basic page of the Entry Property sheet. ** Parameters and return value are as described for standard windows ** 'DialogProc's. */ { #if 0 TRACE4("BsDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: { return BsInit( hwnd, (EINFO* )(((PROPSHEETPAGE* )lparam)->lParam) ); } case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case PSN_APPLY: { BOOL fValid; TRACE("BsAPPLY"); fValid = PeApply( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, (fValid) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ); return TRUE; } case PSN_RESET: { TRACE("BsRESET"); PeCancel( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, FALSE ); break; } } break; } case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); return BsCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } case WM_DESTROY: { PeTerm( hwnd ); break; } } return FALSE; } VOID BsAlternates( IN PEINFO* pInfo ) /* Popup the Alternate Phone Numbers dialog. 'PInfo' is the property ** sheet context. */ { BsPhoneNumberToStash( pInfo ); if (PhoneNumberDlg( pInfo->hwndBs, pInfo->pArgs->fRouter, pInfo->pListPhoneNumbers, &pInfo->fPromoteHuntNumbers )) { TCHAR* pszPhoneNumber; pszPhoneNumber = FirstPszFromList( pInfo->pListPhoneNumbers ); SetWindowText( pInfo->hwndEbPhoneNumber, pszPhoneNumber ); } } BOOL BsCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("BsCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_BS_PB_Configure: BsConfigure( pInfo ); return TRUE; case CID_BS_PB_Alternates: BsAlternates( pInfo ); return TRUE; case CID_BS_CB_UseAreaCountryCodes: BsUpdateAreaAndCountryCode( pInfo ); return TRUE; case CID_BS_LB_CountryCode: { switch (wNotification) { case CBN_DROPDOWN: EuFillCountryCodeList( pInfo->pArgs, pInfo->hwndLbCountryCodes, TRUE ); return TRUE; case CBN_SELCHANGE: EuLbCountryCodeSelChange( pInfo->pArgs, pInfo->hwndLbCountryCodes ); return TRUE; } } case CID_BS_LB_Device: { if (wNotification == CBN_SELCHANGE) BsLbDevicesSelChange( pInfo ); return TRUE; } } return FALSE; } VOID BsConfigure( IN PEINFO* pInfo ) /* Called when the configure button is pressed. 'PInfo' is the property ** sheet context. */ { TRACE("BsConfigure"); if (pInfo->fMultiLinkMode) { /* Multi-link selected. Popup the extended configuration dialog. */ if (MultiLinkConfigureDlg( pInfo->hwndDlg, pInfo->pArgs->pEntry->pdtllistLinks, pInfo->pArgs->fRouter )) { /* The dialog substitutes a list of links with re-allocated nodes ** so need to rebuild the device list so the "pNode" item data ** gets updated. */ PeUpdateShortcuts( pInfo ); BsFillDeviceList( pInfo ); } } else { DTLNODE* pNode; PBLINK* pLink; /* Single-link port is selected. Popup the appropriate device ** configuration dialog. */ pNode = DtlGetFirstNode( pInfo->pArgs->pEntry->pdtllistLinks ); ASSERT(pNode); pLink = (PBLINK* )DtlGetData( pNode ); ASSERT(pLink); DeviceConfigureDlg( pInfo->hwndBs, pLink, TRUE ); } } VOID BsFillDeviceList( IN PEINFO* pInfo ) /* Fill the "dial using" list and set the selection to the one in the ** entry. 'PInfo' is the property sheet context. */ { DTLNODE* pNode; PBLINK* pFirstLink; INT iSel; INT i; TRACE("BsFillDeviceList"); ComboBox_ResetContent( pInfo->hwndLbDevices ); iSel = -1; pFirstLink = NULL; /* Add an item for each link in the entry followed by each unconfigured ** link. */ for (pNode = DtlGetFirstNode( pInfo->pArgs->pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink; TCHAR* psz; pLink = (PBLINK* )DtlGetData( pNode ); if (!pFirstLink) pFirstLink = pLink; psz = DisplayPszFromDeviceAndPort( pLink->pbport.pszDevice, pLink->pbport.pszPort ); if (psz) { ComboBox_AddItemSorted( pInfo->hwndLbDevices, psz, pNode ); Free( psz ); } } /* Add "Multiple Lines" as the last item. */ { TCHAR* pszMultiLink; pszMultiLink = PszFromId( g_hinstDll, SID_MultiLink ); if (pszMultiLink) { i = ComboBox_AddItem( pInfo->hwndLbDevices, pszMultiLink, NULL ); Free( pszMultiLink ); if (pInfo->fMultiLinkMode) { TCHAR* psz; iSel = i; /* Set multi-link phone number behavior. */ psz = PszFromId( g_hinstDll, SID_MultiLinkNumber ); if (psz) { SetWindowText( pInfo->hwndEbPhoneNumber, psz ); Free( psz ); } } } } ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbDevices ); /* Set the selection and set initial window state. */ if (iSel < 0 && pFirstLink) { TCHAR* psz; psz = DisplayPszFromDeviceAndPort( pFirstLink->pbport.pszDevice, pFirstLink->pbport.pszPort ); if (psz) { iSel = ComboBox_FindStringExact( pInfo->hwndLbDevices, -1, psz ); Free( psz ); } } ComboBox_SetCurSel( pInfo->hwndLbDevices, iSel ); pInfo->iLbDevices = iSel; EnableWindow( pInfo->hwndStPhoneNumber, !pInfo->fMultiLinkMode ); EnableWindow( pInfo->hwndEbPhoneNumber, !pInfo->fMultiLinkMode ); EnableWindow( pInfo->hwndPbAlternate, !pInfo->fMultiLinkMode ); } BOOL BsInit( IN HWND hwndPage, IN OUT EINFO* pArgs ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. 'PArgs' is the arguments from the PropertySheet caller. ** ** Return false if focus was set, true otherwise. */ { DWORD dwErr; PEINFO* pInfo; PBENTRY* pEntry; TRACE("BsInit"); /* We're first page, so initialize the property sheet. */ pInfo = PeInit( hwndPage, pArgs ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndBs = hwndPage; pInfo->hwndEbEntryName = GetDlgItem( hwndPage, CID_BS_EB_EntryName ); ASSERT(pInfo->hwndEbEntryName); pInfo->hwndEbDescription = GetDlgItem( hwndPage, CID_BS_EB_Description ); ASSERT(pInfo->hwndEbDescription); pInfo->hwndStCountryCode = GetDlgItem( hwndPage, CID_BS_ST_CountryCode ); ASSERT(pInfo->hwndStCountryCode); pInfo->hwndLbCountryCodes = GetDlgItem( hwndPage, CID_BS_LB_CountryCode ); ASSERT(pInfo->hwndLbCountryCodes); pInfo->hwndStAreaCode = GetDlgItem( hwndPage, CID_BS_ST_AreaCode ); ASSERT(pInfo->hwndStAreaCode); pInfo->hwndLbAreaCodes = GetDlgItem( hwndPage, CID_BS_CL_AreaCode ); ASSERT(pInfo->hwndLbAreaCodes); pInfo->hwndStPhoneNumber = GetDlgItem( hwndPage, CID_BS_ST_PhoneNumber ); ASSERT(pInfo->hwndStPhoneNumber); pInfo->hwndEbPhoneNumber = GetDlgItem( hwndPage, CID_BS_EB_PhoneNumber ); ASSERT(pInfo->hwndEbPhoneNumber); pInfo->hwndPbAlternate = GetDlgItem( hwndPage, CID_BS_PB_Alternates ); ASSERT(pInfo->hwndPbAlternate); pInfo->hwndStDevice = GetDlgItem( hwndPage, CID_BS_ST_Device ); ASSERT(pInfo->hwndStDevice); pInfo->hwndLbDevices = GetDlgItem( hwndPage, CID_BS_LB_Device ); ASSERT(pInfo->hwndLbDevices); pInfo->hwndPbConfigure = GetDlgItem( hwndPage, CID_BS_PB_Configure ); ASSERT(pInfo->hwndPbConfigure); pInfo->hwndCbUseAreaCode = GetDlgItem( hwndPage, CID_BS_CB_UseAreaCountryCodes ); ASSERT(pInfo->hwndCbUseAreaCode); pInfo->hwndCbUseOtherPort = GetDlgItem( hwndPage, CID_BS_CB_UseOtherPort ); ASSERT(pInfo->hwndCbUseOtherPort); /* Calculate the "on" y-position of the controls that slide up when "Use ** Area Code and Country Code" is on, and the offset they slide up when ** it's "off". */ { RECT rectStCountryCode; RECT rectStPhoneNumber; RECT rectEbPhoneNumber; RECT rectPbAlternate; RECT rectStDevice; RECT rectLbDevice; RECT rectPbConfigure; RECT rectCbUseAreaCode; RECT rectCbUseOtherPort; POINT xyStCountryCode; GetWindowRect( pInfo->hwndStCountryCode, &rectStCountryCode ); GetWindowRect( pInfo->hwndStPhoneNumber, &rectStPhoneNumber ); GetWindowRect( pInfo->hwndEbPhoneNumber, &rectEbPhoneNumber ); GetWindowRect( pInfo->hwndPbAlternate, &rectPbAlternate ); GetWindowRect( pInfo->hwndStDevice, &rectStDevice ); GetWindowRect( pInfo->hwndLbDevices, &rectLbDevice ); GetWindowRect( pInfo->hwndPbConfigure, &rectPbConfigure ); GetWindowRect( pInfo->hwndCbUseAreaCode, &rectCbUseAreaCode ); GetWindowRect( pInfo->hwndCbUseOtherPort, &rectCbUseOtherPort ); xyStCountryCode.x = rectStCountryCode.left; xyStCountryCode.y = rectStCountryCode.top; pInfo->xyStPhoneNumber.x = rectStPhoneNumber.left; pInfo->xyStPhoneNumber.y = rectStPhoneNumber.top; pInfo->xyEbPhoneNumber.x = rectEbPhoneNumber.left; pInfo->xyEbPhoneNumber.y = rectEbPhoneNumber.top; pInfo->xyPbAlternate.x = rectPbAlternate.left; pInfo->xyPbAlternate.y = rectPbAlternate.top; pInfo->xyStDevice.x = rectStDevice.left; pInfo->xyStDevice.y = rectStDevice.top; pInfo->xyLbDevice.x = rectLbDevice.left; pInfo->xyLbDevice.y = rectLbDevice.top; pInfo->xyPbConfigure.x = rectPbConfigure.left; pInfo->xyPbConfigure.y = rectPbConfigure.top; pInfo->xyCbUseAreaCode.x = rectCbUseAreaCode.left; pInfo->xyCbUseAreaCode.y = rectCbUseAreaCode.top; pInfo->xyCbUseOtherPort.x = rectCbUseOtherPort.left; pInfo->xyCbUseOtherPort.y = rectCbUseOtherPort.top; ScreenToClient( hwndPage, &xyStCountryCode ); ScreenToClient( hwndPage, &pInfo->xyStPhoneNumber ); ScreenToClient( hwndPage, &pInfo->xyEbPhoneNumber ); ScreenToClient( hwndPage, &pInfo->xyPbAlternate ); ScreenToClient( hwndPage, &pInfo->xyStDevice ); ScreenToClient( hwndPage, &pInfo->xyLbDevice ); ScreenToClient( hwndPage, &pInfo->xyPbConfigure ); ScreenToClient( hwndPage, &pInfo->xyCbUseAreaCode ); ScreenToClient( hwndPage, &pInfo->xyCbUseOtherPort ); pInfo->dyAreaCodeAdjust = pInfo->xyStPhoneNumber.y - xyStCountryCode.y; } /* Initialize page. */ pEntry = pInfo->pArgs->pEntry; /* Entry name field. */ if (!pEntry->pszEntryName) { /* No entry name, so think up a default. */ dwErr = GetDefaultEntryName( pInfo->pArgs->pFile->pdtllistEntries, pInfo->pArgs->fRouter, &pEntry->pszEntryName ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadPage, dwErr, NULL ); PeExit( pInfo, dwErr ); return TRUE; } } Edit_LimitText( pInfo->hwndEbEntryName, RAS_MaxEntryName ); SetWindowText( pInfo->hwndEbEntryName, pEntry->pszEntryName ); Edit_LimitText( pInfo->hwndEbDescription, RAS_MaxDescription ); SetWindowText( pInfo->hwndEbDescription, pEntry->pszDescription ); Edit_LimitText( pInfo->hwndEbPhoneNumber, RAS_MaxPhoneNumber ); SetWindowText( pInfo->hwndEbPhoneNumber, FirstPszFromList( pInfo->pListPhoneNumbers ) ); /* Fill ports/devices list, set selection, and set the state of the phone ** number edit field and button. */ BsFillDeviceList( pInfo ); if (pInfo->pArgs->fRouter) { /* Always checked and invisible for router. This allows some ** optimization in DDM. Ask Gibbs. */ CheckDlgButton( pInfo->hwndBs, CID_BS_CB_UseOtherPort, BST_CHECKED ); EnableWindow( GetDlgItem( hwndPage, CID_BS_CB_UseOtherPort ), FALSE ); ShowWindow( GetDlgItem( hwndPage, CID_BS_CB_UseOtherPort ), SW_HIDE ); } else { /* The "use other port" checkbox is currently per-entry in the UI ** though the phonebook allows it to be per-link. Initialize the ** per-entry copy from the first link. */ ASSERT(pInfo->pLink); CheckDlgButton( pInfo->hwndBs, CID_BS_CB_UseOtherPort, (pInfo->pLink->fOtherPortOk) ? BST_CHECKED : BST_UNCHECKED ); } /* Set "Use country code and area code" checkbox and jockey the fields ** according to the setting. This will trigger filling of the area code ** and country code lists, if necessary. If in router-mode, ** telephony-properties don't apply, since the router service will be ** running in LocalSystem context, for which no telephony settings ** currently exist, so the options are disabled. */ if (pInfo->pArgs->fRouter) { CheckDlgButton( pInfo->hwndBs, CID_BS_CB_UseAreaCountryCodes, BST_UNCHECKED ); BsUpdateAreaAndCountryCode( pInfo ); EnableWindow( GetDlgItem(hwndPage, CID_BS_CB_UseAreaCountryCodes), FALSE ); ShowWindow( GetDlgItem(hwndPage, CID_BS_CB_UseAreaCountryCodes), SW_HIDE ); } else { CheckDlgButton( pInfo->hwndBs, CID_BS_CB_UseAreaCountryCodes, (pEntry->fUseCountryAndAreaCode) ? BST_CHECKED : BST_UNCHECKED ); BsUpdateAreaAndCountryCode( pInfo ); } if (pInfo->pArgs->pApiArgs->dwFlags & RASEDFLAG_NoRename) EnableWindow( pInfo->hwndEbEntryName, FALSE ); return TRUE; } VOID BsLbDevicesSelChange( IN PEINFO* pInfo ) /* Called when device selection has changed. 'PInfo' is the property ** sheet context. */ { DTLNODE* pNodeSel; INT iSel; TRACE("BsLbDevicesSelChange"); iSel = ComboBox_GetCurSel( pInfo->hwndLbDevices ); if (iSel == pInfo->iLbDevices) return; pNodeSel = ComboBox_GetItemDataPtr( pInfo->hwndLbDevices, iSel ); if (pNodeSel) { DTLNODE* pNode; if (pInfo->fMultiLinkMode && PeCountEnabledLinks( pInfo ) > 1) { MSGARGS msgargs; /* User just turned off multi-link mode, make sure he means it ** because the port/link data associated with the 2nd-to-nth links ** will be discarded. */ ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_YESNO + MB_DEFBUTTON2 + MB_ICONEXCLAMATION; if (MsgDlg( pInfo->hwndBs, SID_UnMultiLink, &msgargs ) != IDYES) { /* User has cancelled un-multi-link. Restore previous ** selection. */ ComboBox_SetCurSel( pInfo->hwndLbDevices, pInfo->iLbDevices ); return; } } /* Disable all but the selected link. */ for (pNode = DtlGetFirstNode( pInfo->pArgs->pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink; pLink = (PBLINK* )DtlGetData( pNode );; pLink->fEnabled = (pNode == pNodeSel); } /* Move the selected node to the head of the list of links. */ DtlRemoveNode( pInfo->pArgs->pEntry->pdtllistLinks, pNodeSel ); DtlAddNodeFirst( pInfo->pArgs->pEntry->pdtllistLinks, pNodeSel ); if (pInfo->fMultiLinkMode) { /* Reset phone number to single-link mode. */ EuPhoneNumberStashFromEntry( pInfo->pArgs, &pInfo->pListPhoneNumbers, &pInfo->fPromoteHuntNumbers ); SetWindowText( pInfo->hwndEbPhoneNumber, FirstPszFromList( pInfo->pListPhoneNumbers ) ); EnableWindow( pInfo->hwndStPhoneNumber, TRUE ); EnableWindow( pInfo->hwndEbPhoneNumber, TRUE ); EnableWindow( pInfo->hwndPbAlternate, TRUE ); pInfo->fMultiLinkMode = FALSE; } } else { TCHAR* psz; /* User just turned on multi-link mode. */ if (pInfo->pArgs->pEntry->dwBaseProtocol != BP_Ppp) { MsgDlg( pInfo->hwndDlg, SID_MlinkNeedsPpp, NULL ); ComboBox_SetCurSel( pInfo->hwndLbDevices, pInfo->iLbDevices ); return; } /* Set multi-link phone number behavior. */ BsPhoneNumberToStash( pInfo ); EuPhoneNumberStashToEntry( pInfo->pArgs, pInfo->pListPhoneNumbers, pInfo->fPromoteHuntNumbers, FALSE ); psz = PszFromId( g_hinstDll, SID_MultiLinkNumber ); if (psz) { SetWindowText( pInfo->hwndEbPhoneNumber, psz ); Free( psz ); } EnableWindow( pInfo->hwndStPhoneNumber, FALSE ); EnableWindow( pInfo->hwndEbPhoneNumber, FALSE ); EnableWindow( pInfo->hwndPbAlternate, FALSE ); pInfo->fMultiLinkMode = TRUE; } pInfo->iLbDevices = iSel; } VOID BsPhoneNumberToStash( IN PEINFO* pInfo ) /* Replace the first phonenumber in the stashed list with the contents of ** the phone number field. 'pInfo' is the property sheet context. */ { DWORD dwErr; TCHAR* pszPhoneNumber; TRACE("BsPhoneNumberToStash"); ASSERT(!(pInfo->fMultiLinkMode&&pInfo->iLbDevices>=0)); pszPhoneNumber = GetText( pInfo->hwndEbPhoneNumber ); if (pszPhoneNumber) { dwErr = FirstPszToList( pInfo->pListPhoneNumbers, pszPhoneNumber ); Free( pszPhoneNumber ); } else dwErr = ERROR_NOT_ENOUGH_MEMORY; if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_RetrievingData, dwErr, NULL ); PeExit( pInfo, dwErr ); } } VOID BsUpdateAreaAndCountryCode( IN PEINFO* pInfo ) /* Handles enabling/disabling and moving the Area Code and Country Code ** control and those controls below them based on the setting of the "Use ** area code and country code" checkbox. 'PInfo' is the dialog context. */ { HWND hwndFocus; BOOL fEnable; TRACE("BsUpdateAreaAndCountryCode"); fEnable = IsDlgButtonChecked( pInfo->hwndBs, CID_BS_CB_UseAreaCountryCodes ); if (fEnable) { /* The area code and country code lists are being activated, so fill ** the lists if they aren't already. */ EuFillCountryCodeList( pInfo->pArgs, pInfo->hwndLbCountryCodes, FALSE ); EuFillAreaCodeList( pInfo->pArgs, pInfo->hwndLbAreaCodes ); } else { /* If the focus is on one of the controls we're about to disable, move ** it to the entry phone number editbox. Otherwise, keyboard user is ** stuck. */ hwndFocus = GetFocus(); if (hwndFocus == pInfo->hwndLbCountryCodes || hwndFocus == pInfo->hwndLbAreaCodes) { SetFocus( pInfo->hwndEbPhoneNumber ); } } /* Enable/disable show/hide the Area Code and Country Code controls as ** indicated by user. */ { int nCmdShow = (fEnable) ? SW_SHOW : SW_HIDE; EnableWindow( pInfo->hwndStAreaCode, fEnable ); ShowWindow( pInfo->hwndStAreaCode, nCmdShow ); EnableWindow( pInfo->hwndLbAreaCodes, fEnable ); ShowWindow( pInfo->hwndLbAreaCodes, nCmdShow ); EnableWindow( pInfo->hwndStCountryCode, fEnable ); ShowWindow( pInfo->hwndStCountryCode, nCmdShow ); EnableWindow( pInfo->hwndLbCountryCodes, fEnable ); ShowWindow( pInfo->hwndLbCountryCodes, nCmdShow ); } /* Move the controls below the area and country codes up/down depending on ** whether the area code and country code controls are visible. */ { int yStPhoneNumber; int yEbPhoneNumber; int yPbAlternate; int yStDevice; int yLbDevice; int yPbConfigure; int yCbUseAreaCode; int yCbUseOtherPort; if (fEnable) { yStPhoneNumber = pInfo->xyStPhoneNumber.y; yEbPhoneNumber = pInfo->xyEbPhoneNumber.y; yPbAlternate = pInfo->xyPbAlternate.y; yStDevice = pInfo->xyStDevice.y; yLbDevice = pInfo->xyLbDevice.y; yPbConfigure = pInfo->xyPbConfigure.y; yCbUseAreaCode = pInfo->xyCbUseAreaCode.y; yCbUseOtherPort = pInfo->xyCbUseOtherPort.y; } else { yStPhoneNumber = pInfo->xyStPhoneNumber.y - pInfo->dyAreaCodeAdjust; yEbPhoneNumber = pInfo->xyEbPhoneNumber.y - pInfo->dyAreaCodeAdjust; yPbAlternate = pInfo->xyPbAlternate.y - pInfo->dyAreaCodeAdjust; yStDevice = pInfo->xyStDevice.y - pInfo->dyAreaCodeAdjust; yLbDevice = pInfo->xyLbDevice.y - pInfo->dyAreaCodeAdjust; yPbConfigure = pInfo->xyPbConfigure.y - pInfo->dyAreaCodeAdjust; yCbUseAreaCode = pInfo->xyCbUseAreaCode.y - pInfo->dyAreaCodeAdjust; yCbUseOtherPort = pInfo->xyCbUseOtherPort.y - pInfo->dyAreaCodeAdjust; } SetWindowPos( pInfo->hwndStPhoneNumber, NULL, pInfo->xyStPhoneNumber.x, yStPhoneNumber, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndEbPhoneNumber, NULL, pInfo->xyEbPhoneNumber.x, yEbPhoneNumber, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndPbAlternate, NULL, pInfo->xyPbAlternate.x, yPbAlternate, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndStDevice, NULL, pInfo->xyStDevice.x, yStDevice, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndLbDevices, NULL, pInfo->xyLbDevice.x, yLbDevice, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndPbConfigure, NULL, pInfo->xyPbConfigure.x, yPbConfigure, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndCbUseAreaCode, NULL, pInfo->xyCbUseAreaCode.x, yCbUseAreaCode, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); SetWindowPos( pInfo->hwndCbUseOtherPort, NULL, pInfo->xyCbUseOtherPort.x, yCbUseOtherPort, 0, 0, SWP_NOSIZE + SWP_NOZORDER + SWP_NOCOPYBITS ); } } /*---------------------------------------------------------------------------- ** Server property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK SvDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Server page of the Entry property sheet. ** Parameters and return value are as described for standard windows ** 'DialogProc's. */ { #if 0 TRACE4("SvDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return SvInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); return SvCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } case WM_NOTIFY: { if (((NMHDR* )lparam)->code == PSN_SETACTIVE) { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (!pInfo->pArgs->fRouter) break; /* Use the server type label to the built information field ** instead. */ { TCHAR* pszFormat; TCHAR* pszFormatted; TCHAR* pszEntry; TCHAR* apszArgs[ 2 ]; TCHAR szRouterName[ MAX_COMPUTERNAME_LENGTH + 1 ]; DWORD dwSize; pszFormat = PszFromId( g_hinstDll, SID_ProtocolsInfo ); if (pszFormat) { dwSize = MAX_COMPUTERNAME_LENGTH + 1; szRouterName[ 0 ] = '\0'; GetComputerName( szRouterName, &dwSize ); pszEntry = GetText( pInfo->hwndEbEntryName ); if (pszEntry) { apszArgs[ 0 ] = szRouterName; apszArgs[ 1 ] = pszEntry; pszFormatted = NULL; FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, pszFormat, 0, 0, (LPTSTR )&pszFormatted, 2, (va_list* )apszArgs ); Free( pszFormat ); Free( pszEntry ); if (pszFormatted) { SetWindowText( pInfo->hwndStServerTypes, pszFormatted ); LocalFree( pszFormatted ); } } } } } break; } } return FALSE; } VOID SvCbIpClicked( IN PEINFO* pInfo ) /* Called when the TCP/IP checkbox is clicked. 'PInfo' is the property ** sheet context. */ { DWORD dwBaseProtocol; BOOL fChecked; BOOL fInstalled; INT iSel; iSel = ComboBox_GetCurSel( pInfo->hwndLbServerTypes ); dwBaseProtocol = (DWORD)ComboBox_GetItemData( pInfo->hwndLbServerTypes, iSel ); fChecked = Button_GetCheck( pInfo->hwndCbIp ); fInstalled = (pInfo->dwfInstalledProtocols & NP_Ip); if (fChecked && !fInstalled) { /* Can't check if not installed. */ SvProtocolNotInstalledPopup( pInfo, SID_Ip ); Button_SetCheck( pInfo->hwndCbIp, FALSE ); return; } if (dwBaseProtocol == BP_Slip && !fChecked && fInstalled) { /* Can't uncheck on SLIP. */ MsgDlg( pInfo->hwndSv, SID_SlipNeedsIp, NULL ); Button_SetCheck( pInfo->hwndCbIp, TRUE ); return; } pInfo->fPppIp = fChecked; EnableWindow( pInfo->hwndPbIp, fChecked ); } VOID SvCbIpxClicked( IN PEINFO* pInfo ) /* Called when the IPX checkbox is clicked. 'PInfo' is the property sheet ** context. */ { BOOL fChecked; BOOL fInstalled; fChecked = Button_GetCheck( pInfo->hwndCbIpx ); fInstalled = (pInfo->dwfInstalledProtocols & NP_Ipx); if (fChecked && !fInstalled) { /* Can't check if not installed. */ SvProtocolNotInstalledPopup( pInfo, SID_Ipx ); Button_SetCheck( pInfo->hwndCbIpx, FALSE ); } pInfo->fPppIpx = fChecked; } VOID SvCbNbfClicked( IN PEINFO* pInfo ) /* Called when the Netbeui checkbox is clicked. 'PInfo' is the property ** sheet context. */ { DWORD dwBaseProtocol; BOOL fChecked; BOOL fInstalled; INT iSel; ASSERT(!pInfo->pArgs->fRouter); iSel = ComboBox_GetCurSel( pInfo->hwndLbServerTypes ); dwBaseProtocol = (DWORD)ComboBox_GetItemData( pInfo->hwndLbServerTypes, iSel ); fChecked = Button_GetCheck( pInfo->hwndCbNbf ); fInstalled = (pInfo->dwfInstalledProtocols & NP_Nbf); if (fChecked && !fInstalled) { /* Can't check if not installed. */ SvProtocolNotInstalledPopup( pInfo, SID_Nbf ); Button_SetCheck( pInfo->hwndCbNbf, FALSE ); return; } if (dwBaseProtocol == BP_Ras && !fChecked && fInstalled) { /* Can't uncheck on RAS. */ MsgDlg( pInfo->hwndSv, SID_RasNeedsNbf, NULL ); Button_SetCheck( pInfo->hwndCbNbf, TRUE ); } pInfo->fPppNbf = fChecked; } BOOL SvCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("SvCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_SV_LB_ServerType: if (wNotification == CBN_SELCHANGE) SvLbServerTypesSelChange( pInfo ); return TRUE; case CID_SV_CB_TcpIp: if (wNotification == BN_CLICKED) SvCbIpClicked( pInfo ); return TRUE; case CID_SV_CB_Ipx: if (wNotification == BN_CLICKED) SvCbIpxClicked( pInfo ); return TRUE; case CID_SV_CB_Netbeui: if (wNotification == BN_CLICKED) SvCbNbfClicked( pInfo ); return TRUE; case CID_SV_PB_TcpIpSettings: SvTcpipSettings( pInfo ); return TRUE; case CID_SV_CB_SwCompression: if (wNotification == BN_CLICKED) { pInfo->fSwCompression = Button_GetCheck( pInfo->hwndCbSwCompression ); } return TRUE; case CID_SV_CB_LcpExtensions: if (wNotification == BN_CLICKED) { pInfo->fLcpExtensions = Button_GetCheck( pInfo->hwndCbLcpExtensions ); } return TRUE; } return FALSE; } BOOL SvInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { PEINFO* pInfo; PBENTRY* pEntry; HWND hwndLb; INT i; INT iSel; TRACE("SvInit"); pInfo = PeContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndSv = hwndPage; pInfo->hwndStServerTypes = GetDlgItem( hwndPage, CID_SV_ST_ServerType ); ASSERT(pInfo->hwndStServerTypes); pInfo->hwndLbServerTypes = GetDlgItem( hwndPage, CID_SV_LB_ServerType ); ASSERT(pInfo->hwndLbServerTypes); pInfo->hwndCbIp = GetDlgItem( hwndPage, CID_SV_CB_TcpIp ); ASSERT(pInfo->hwndCbIp); pInfo->hwndPbIp = GetDlgItem( hwndPage, CID_SV_PB_TcpIpSettings ); ASSERT(pInfo->hwndPbIp); pInfo->hwndCbIpx = GetDlgItem( hwndPage, CID_SV_CB_Ipx ); ASSERT(pInfo->hwndCbIpx); pInfo->hwndCbNbf = GetDlgItem( hwndPage, CID_SV_CB_Netbeui ); ASSERT(pInfo->hwndCbNbf); pInfo->hwndCbSwCompression = GetDlgItem( hwndPage, CID_SV_CB_SwCompression ); ASSERT(pInfo->hwndCbSwCompression); pInfo->hwndCbLcpExtensions = GetDlgItem( hwndPage, CID_SV_CB_LcpExtensions ); ASSERT(pInfo->hwndCbLcpExtensions); /* Initialize page. */ pEntry = pInfo->pArgs->pEntry; #ifdef RASMERGE pInfo->dwfInstalledProtocols = g_pGetInstalledProtocols(); #else pInfo->dwfInstalledProtocols = GetInstalledProtocols(); #endif if (pInfo->pArgs->fRouter) { /* Just in case somebody dicked with the phonebook. */ pInfo->dwBaseProtocolDefault = BP_Ppp; /* Disable/hide the server type window which we build in the ** background to keep our lives simple. */ EnableWindow( pInfo->hwndLbServerTypes, FALSE ); ShowWindow( pInfo->hwndLbServerTypes, SW_HIDE ); } pInfo->dwBaseProtocolDefault = pEntry->dwBaseProtocol; pInfo->fPppIpDefault = pInfo->fPppIp = (pInfo->dwfInstalledProtocols & NP_Ip) && !(pEntry->dwfExcludedProtocols & NP_Ip); pInfo->fPppIpxDefault = pInfo->fPppIpx = (pInfo->dwfInstalledProtocols & NP_Ipx) && !(pEntry->dwfExcludedProtocols & NP_Ipx); pInfo->fPppNbfDefault = pInfo->fPppNbf = (pInfo->dwfInstalledProtocols & NP_Nbf) && !(pEntry->dwfExcludedProtocols & NP_Nbf); pInfo->fSwCompression = pEntry->fSwCompression; pInfo->fLcpExtensions = pEntry->fLcpExtensions; /* Fill server type list, noting which item should be selected. */ iSel = 0; ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbServerTypes, SID_ST_Ppp, (VOID* )BP_Ppp ); if (!pInfo->pArgs->fRouter) { i = ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbServerTypes, SID_ST_Slip, (VOID* )BP_Slip ); if (pEntry->dwBaseProtocol == BP_Slip) iSel = i; #ifdef AMB i = ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbServerTypes, SID_ST_Ras, (VOID* )BP_Ras ); if (pEntry->dwBaseProtocol == BP_Ras) iSel = i; #endif } ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbServerTypes ); /* Select server type with notification to trigger check box updates. */ ComboBox_SetCurSelNotify( pInfo->hwndLbServerTypes, iSel ); SetFocus( pInfo->hwndLbServerTypes ); return FALSE; } VOID SvLbServerTypesSelChange( IN PEINFO* pInfo ) /* Called when the server type is changed. 'PInfo' is the property sheet ** context. */ { INT iSel; DWORD dwBaseProtocol; iSel = ComboBox_GetCurSel( pInfo->hwndLbServerTypes ); dwBaseProtocol = (DWORD)ComboBox_GetItemData( pInfo->hwndLbServerTypes, iSel ); switch (dwBaseProtocol) { case BP_Ppp: { EnableWindow( pInfo->hwndCbIp, TRUE ); EnableWindow( pInfo->hwndPbIp, TRUE ); EnableWindow( pInfo->hwndCbIpx, TRUE ); EnableWindow( pInfo->hwndCbNbf, TRUE ); EnableWindow( pInfo->hwndCbSwCompression, TRUE ); EnableWindow( pInfo->hwndCbLcpExtensions, TRUE ); Button_SetCheck( pInfo->hwndCbIp, pInfo->fPppIp ); EnableWindow( pInfo->hwndPbIp, pInfo->fPppIp ); Button_SetCheck( pInfo->hwndCbIpx, pInfo->fPppIpx ); Button_SetCheck( pInfo->hwndCbNbf, pInfo->fPppNbf ); Button_SetCheck( pInfo->hwndCbSwCompression, pInfo->fSwCompression ); Button_SetCheck( pInfo->hwndCbLcpExtensions, pInfo->fLcpExtensions ); break; } case BP_Slip: { if (pInfo->fMultiLinkMode) { MsgDlg( pInfo->hwndDlg, SID_MlinkNeedsPpp, NULL ); ComboBox_SetCurSel( pInfo->hwndLbServerTypes, pInfo->iLbServerTypes ); return; } EnableWindow( pInfo->hwndCbIp, TRUE ); EnableWindow( pInfo->hwndPbIp, TRUE ); EnableWindow( pInfo->hwndCbIpx, FALSE ); EnableWindow( pInfo->hwndCbNbf, FALSE ); EnableWindow( pInfo->hwndCbSwCompression, FALSE ); EnableWindow( pInfo->hwndCbLcpExtensions, FALSE ); Button_SetCheck( pInfo->hwndCbIp, pInfo->dwfInstalledProtocols & NP_Ip ); EnableWindow( pInfo->hwndPbIp, pInfo->dwfInstalledProtocols & NP_Ip ); Button_SetCheck( pInfo->hwndCbIpx, FALSE ); Button_SetCheck( pInfo->hwndCbNbf, FALSE ); Button_SetCheck( pInfo->hwndCbSwCompression, FALSE ); Button_SetCheck( pInfo->hwndCbLcpExtensions, FALSE ); break; } #ifdef AMB case BP_Ras: { if (pInfo->fMultiLinkMode) { MsgDlg( pInfo->hwndDlg, SID_MlinkNeedsPpp, NULL ); ComboBox_SetCurSel( pInfo->hwndLbServerTypes, pInfo->iLbServerTypes ); return; } EnableWindow( pInfo->hwndCbIp, FALSE ); EnableWindow( pInfo->hwndPbIp, FALSE ); EnableWindow( pInfo->hwndCbIpx, FALSE ); EnableWindow( pInfo->hwndCbNbf, TRUE ); EnableWindow( pInfo->hwndCbLcpExtensions, FALSE ); EnableWindow( pInfo->hwndCbSwCompression, TRUE ); Button_SetCheck( pInfo->hwndCbIp, FALSE ); EnableWindow( pInfo->hwndPbIp, FALSE ); Button_SetCheck( pInfo->hwndCbIpx, FALSE ); Button_SetCheck( pInfo->hwndCbNbf, pInfo->dwfInstalledProtocols & NP_Nbf ); Button_SetCheck( pInfo->hwndCbSwCompression, pInfo->fSwCompression ); Button_SetCheck( pInfo->hwndCbLcpExtensions, FALSE ); break; } #endif } /* Save current index so can back out of a selection later if necessary. ** Save base protocol so the BS:LbDevices can check it and decide if ** Multiple Lines is allowed. */ pInfo->iLbServerTypes = iSel; pInfo->pArgs->pEntry->dwBaseProtocol = dwBaseProtocol; } VOID SvProtocolNotInstalledPopup( IN PEINFO* pInfo, IN DWORD dwSid ) /* Popup a message explaining to user that the protocol is not installed ** and cannot be checked. 'PInfo' is the property sheet context. 'DwSid' ** is a string ID for a network protocol. */ { MSGARGS msgargs; TCHAR* pszArg; pszArg = PszFromId( g_hinstDll, dwSid ); if (!pszArg) return; ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.apszArgs[ 0 ] = pszArg; MsgDlg( pInfo->hwndSv, SID_NpNotInstalled, &msgargs ); Free( pszArg ); } VOID SvTcpipSettings( IN PEINFO* pInfo ) /* Called when TCP/IP Settings button is pressed. 'PInfo' is the property ** sheet context. */ { DWORD dwBaseProtocol; dwBaseProtocol = (DWORD)ComboBox_GetItemData( pInfo->hwndLbServerTypes, ComboBox_GetCurSel( pInfo->hwndLbServerTypes ) ); if (dwBaseProtocol == BP_Ppp) { PppTcpipDlg( pInfo->hwndDlg, pInfo->pArgs->pEntry, pInfo->pArgs->fRouter ); } else { ASSERT(dwBaseProtocol==BP_Slip); SlipTcpipDlg( pInfo->hwndDlg, pInfo->pArgs->pEntry ); } } /*---------------------------------------------------------------------------- ** Script property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK ScDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Script page of the Entry property sheet. ** Parameters and return value are as described for standard windows ** 'DialogProc's. */ { #if 0 TRACE4("ScDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return ScInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); return ScCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } } return FALSE; } BOOL ScCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("ScCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_SC_PB_Refresh: { INT iSel; TCHAR* pszSel; iSel = ComboBox_GetCurSel( pInfo->hwndLbScript ); if (iSel > 0) pszSel = ComboBox_GetPsz( pInfo->hwndLbScript, iSel ); else pszSel = NULL; EuFillDoubleScriptsList( pInfo->pArgs, pInfo->hwndLbScript, pszSel ); Free0( pszSel ); return TRUE; } case CID_SC_PB_Edit: { TCHAR* psz; psz = GetText( pInfo->hwndLbScript ); if (psz) { if (FileExists( psz )) EuEditScpScript( pInfo->hwndDlg, psz ); else EuEditSwitchInf( pInfo->hwndDlg ); Free( psz ); } return TRUE; } case CID_SC_PB_Before: { BeforeDialDlg( pInfo->hwndDlg, pInfo->pArgs ); return TRUE; } case CID_SC_RB_None: case CID_SC_RB_Terminal: case CID_SC_RB_Script: { /* Scripts listbox is gray unless script mode is selected. */ if (wNotification == BN_CLICKED) EnableWindow( pInfo->hwndLbScript, (wId == CID_SC_RB_Script) ); break; } } return FALSE; } BOOL ScInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { PEINFO* pInfo; TRACE("ScInit"); pInfo = PeContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndSc = hwndPage; pInfo->hwndRbNone = GetDlgItem( hwndPage, CID_SC_RB_None ); ASSERT(pInfo->hwndRbNone); pInfo->hwndRbTerminal = GetDlgItem( hwndPage, CID_SC_RB_Terminal ); ASSERT(pInfo->hwndRbTerminal); pInfo->hwndRbScript = GetDlgItem( hwndPage, CID_SC_RB_Script ); ASSERT(pInfo->hwndRbScript); pInfo->hwndLbScript = GetDlgItem( hwndPage, CID_SC_LB_Script ); ASSERT(pInfo->hwndLbScript); pInfo->hwndPbEdit = GetDlgItem( hwndPage, CID_SC_PB_Edit ); ASSERT(pInfo->hwndPbEdit); pInfo->hwndPbRefresh = GetDlgItem( hwndPage, CID_SC_PB_Refresh ); ASSERT(pInfo->hwndPbRefresh); /* Fill list boxes and set the selection. */ EuFillDoubleScriptsList( pInfo->pArgs, pInfo->hwndLbScript, pInfo->pArgs->pEntry->pszScriptAfter ); /* Select the correct modes. */ { HWND hwndRb; DWORD dwScriptMode; dwScriptMode = pInfo->pArgs->pEntry->dwScriptModeAfter; if (dwScriptMode == SM_Terminal && !pInfo->pArgs->fRouter) hwndRb = pInfo->hwndRbTerminal; else if (dwScriptMode == SM_Script) hwndRb = pInfo->hwndRbScript; else hwndRb = pInfo->hwndRbNone; SendMessage( hwndRb, BM_CLICK, 0, 0 ); } return TRUE; } /*---------------------------------------------------------------------------- ** Security property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK SeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Security page of the Entry property sheet. ** Parameters and return value are as described for standard windows ** 'DialogProc's. */ { #if 0 TRACE4("SeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return SeInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); return SeCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } } return FALSE; } BOOL SeCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("SeCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_SE_RB_AnyAuth: case CID_SE_RB_EncryptedAuth: { if (wNotification == BN_CLICKED) { EnableWindow( pInfo->hwndCbDataEncryption, FALSE ); EnableWindow( pInfo->hwndCbStrongDataEncryption, FALSE ); Button_SetCheck( pInfo->hwndCbDataEncryption, FALSE ); Button_SetCheck( pInfo->hwndCbStrongDataEncryption, FALSE ); pInfo->fStrongDataEncryption = FALSE; pInfo->fDataEncryption = FALSE; if (!pInfo->pArgs->fRouter) { EnableWindow( pInfo->hwndCbUseLogon, FALSE ); Button_SetCheck( pInfo->hwndCbUseLogon, FALSE ); pInfo->fUseLogon = FALSE; } } return TRUE; } case CID_SE_RB_MsEncryptedAuth: { if (wNotification == BN_CLICKED) { EnableWindow( pInfo->hwndCbDataEncryption, TRUE ); Button_SetCheck( pInfo->hwndCbDataEncryption, pInfo->fDataEncryption ); if (!pInfo->pArgs->fRouter) { EnableWindow( pInfo->hwndCbUseLogon, TRUE ); Button_SetCheck( pInfo->hwndCbUseLogon, pInfo->fUseLogon ); } if (pInfo->fDataEncryption) { EnableWindow( pInfo->hwndCbStrongDataEncryption, TRUE ); Button_SetCheck( pInfo->hwndCbStrongDataEncryption, pInfo->fStrongDataEncryption ); } else { EnableWindow( pInfo->hwndCbStrongDataEncryption, FALSE ); } break; } return TRUE; } case CID_SE_CB_RequireDataEncryption: { if (wNotification == BN_CLICKED) { BOOL fChecked = Button_GetCheck( pInfo->hwndCbDataEncryption ); if (!pInfo->fEncryptionPermitted && fChecked) { MsgDlg( pInfo->hwndSe, SID_EncryptionBanned, NULL ); Button_SetCheck( pInfo->hwndCbDataEncryption, FALSE ); Button_SetCheck( pInfo->hwndCbStrongDataEncryption, FALSE ); break; } EnableWindow( pInfo->hwndCbStrongDataEncryption, fChecked ); if (fChecked) { Button_SetCheck( pInfo->hwndCbStrongDataEncryption, pInfo->fStrongDataEncryption ); } else { Button_SetCheck( pInfo->hwndCbStrongDataEncryption, FALSE ); pInfo->fStrongDataEncryption = FALSE; } pInfo->fDataEncryption = fChecked; } return TRUE; } case CID_SE_CB_RequireStrongDataEncryption: { if (wNotification == BN_CLICKED) { BOOL fChecked = Button_GetCheck( pInfo->hwndCbStrongDataEncryption ); pInfo->fStrongDataEncryption = fChecked; } return TRUE; } case CID_SE_CB_UseLogonCredentials: { if (wNotification == BN_CLICKED) pInfo->fUseLogon = Button_GetCheck( pInfo->hwndCbUseLogon ); return TRUE; } case CID_SE_PB_UnsavePw: { DWORD dwErr; RASCREDENTIALS rc; /* Uncache the password so user is prompted again. */ ZeroMemory( &rc, sizeof(rc) ); rc.dwSize = sizeof(rc); rc.dwMask = RASCM_Password; ASSERT(g_pRasSetCredentials); TRACE("RasSetCredentials(p,TRUE)"); dwErr = g_pRasSetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pszEntry, &rc, TRUE ); TRACE1("RasSetCredentials=%d",dwErr); if (dwErr == 0) { /* No longer a cached password, so gray the button, but move ** the focus to OK first so keyboard only user is not stuck. */ PostMessage( pInfo->hwndDlg, WM_NEXTDLGCTL, (WPARAM )GetDlgItem( pInfo->hwndDlg, IDOK ), TRUE ); EnableWindow( pInfo->hwndPbUnsavePw, FALSE ); } else ErrorDlg( pInfo->hwndDlg, SID_OP_UncachePw, dwErr, NULL ); return TRUE; } } return FALSE; } BOOL SeInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { PEINFO* pInfo; PBENTRY* pEntry; TRACE("SeInit"); pInfo = PeContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndSe = hwndPage; pInfo->hwndRbAnyAuth = GetDlgItem( hwndPage, CID_SE_RB_AnyAuth ); ASSERT(pInfo->hwndRbAnyAuth); pInfo->hwndRbEncryptedAuth = GetDlgItem( hwndPage, CID_SE_RB_EncryptedAuth ); ASSERT(pInfo->hwndRbEncryptedAuth); pInfo->hwndRbMsEncryptedAuth = GetDlgItem( hwndPage, CID_SE_RB_MsEncryptedAuth ); ASSERT(pInfo->hwndRbMsEncryptedAuth); pInfo->hwndCbDataEncryption = GetDlgItem( hwndPage, CID_SE_CB_RequireDataEncryption ); ASSERT(pInfo->hwndCbDataEncryption); pInfo->hwndCbStrongDataEncryption = GetDlgItem( hwndPage, CID_SE_CB_RequireStrongDataEncryption ); ASSERT(pInfo->hwndCbStrongDataEncryption); pInfo->hwndPbUnsavePw = GetDlgItem( hwndPage, CID_SE_PB_UnsavePw ); ASSERT(pInfo->hwndPbUnsavePw ); pInfo->hwndCbSecureFiles = GetDlgItem( hwndPage, CID_SE_CB_SecureLocalFiles ); ASSERT(pInfo->hwndCbSecureFiles ); pEntry = pInfo->pArgs->pEntry; if (pInfo->pArgs->fRouter) { pInfo->hwndCbAuthenticateServer = GetDlgItem( hwndPage, CID_SE_CB_AuthenticateServer ); ASSERT(pInfo->hwndCbAuthenticateServer); Button_SetCheck( pInfo->hwndCbAuthenticateServer, pEntry->fAuthenticateServer ); } else { pInfo->hwndCbUseLogon = GetDlgItem( hwndPage, CID_SE_CB_UseLogonCredentials ); ASSERT(pInfo->hwndCbUseLogon); } pInfo->fEncryptionPermitted = IsEncryptionPermitted(); if (!pInfo->fEncryptionPermitted) pEntry->dwDataEncryption = DE_None; pInfo->fDataEncryption = (pEntry->dwDataEncryption >= DE_Weak); pInfo->fStrongDataEncryption = (pEntry->dwDataEncryption >= DE_Strong); pInfo->fUseLogon = pEntry->fAutoLogon; Button_SetCheck( pInfo->hwndCbSecureFiles, pEntry->fSecureLocalFiles ); /* Select the correct authentication mode with a pseudo-click which will ** trigger enabling/disabling of checkbox state. */ { HWND hwndRb; if (pEntry->dwAuthRestrictions == AR_AuthAny) hwndRb = pInfo->hwndRbAnyAuth; else if (pEntry->dwAuthRestrictions == AR_AuthEncrypted) hwndRb = pInfo->hwndRbEncryptedAuth; else { ASSERT(pEntry->dwAuthRestrictions==AR_AuthMsEncrypted); hwndRb = pInfo->hwndRbMsEncryptedAuth; } SendMessage( hwndRb, BM_CLICK, 0, 0 ); } if (pInfo->pArgs->fNoUser || pInfo->pArgs->fRouter) { /* Unsave password button is hidden during logon and when working on ** the router phonebook since passwords cannot be saved when dialing ** in those cases. */ EnableWindow( pInfo->hwndPbUnsavePw, FALSE ); ShowWindow( pInfo->hwndPbUnsavePw, SW_HIDE ); } else { BOOL fEdit; BOOL fChanged; BOOL fSavedPw; /* Enable/disable the "Unsave password" button depending on the ** existence of a cached password. */ fSavedPw = FALSE; EuGetEditFlags( pInfo->pArgs, &fEdit, &fChanged ); // // !!! If RAS is not installed on the local system, // then we cannot call RasGetCredentials. This is not // critical, since this only affects a router installation // and they do not use this functionality anyway. // if (fEdit && g_pRasGetCredentials != NULL) { DWORD dwErrRc; RASCREDENTIALS rc; ZeroMemory( &rc, sizeof(rc) ); rc.dwSize = sizeof(rc); rc.dwMask = RASCM_Password; ASSERT(g_pRasGetCredentials); TRACE("RasGetCredentials"); dwErrRc = g_pRasGetCredentials( pInfo->pArgs->pFile->pszPath, pInfo->pArgs->pszEntry, &rc ); TRACE2("RasGetCredentials=%d,m=%d",dwErrRc,rc.dwMask); if (dwErrRc == 0 && (rc.dwMask & RASCM_Password)) fSavedPw = TRUE; } EnableWindow( pInfo->hwndPbUnsavePw, fSavedPw ); } return TRUE; } /*---------------------------------------------------------------------------- ** X.25 property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK XsDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the X.25 page of the Entry property sheet. ** Parameters and return value are as described for standard windows ** 'DialogProc's. */ { #if 0 TRACE4("XsDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return XsInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; } return FALSE; } VOID XsFillPadsList( IN PEINFO* pInfo, IN BOOL fLocalPad ) /* Fill PADs list if it's not already, and select the PAD from user's ** entry. 'PInfo' is the property sheet context. 'fLocalPad' is true if ** the entry device is a local PAD card, false otherwise. */ { DWORD dwErr; INT cPads; DTLNODE* pNode; INT nIndex; TRACE("XsFillPadsList"); cPads = ComboBox_GetCount( pInfo->hwndLbX25Pads ); if (cPads > 1 || (fLocalPad && cPads == 1)) return; ComboBox_ResetContent( pInfo->hwndLbX25Pads ); ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbX25Pads, SID_NoneSelected, NULL ); ComboBox_SetCurSel( pInfo->hwndLbX25Pads, 0 ); if (!fLocalPad) { PBENTRY* pEntry; ASSERT(!pInfo->pListPads); dwErr = LoadPadsList( &pInfo->pListPads ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadX25Info, dwErr, NULL ); return; } pEntry = pInfo->pArgs->pEntry; for (pNode = DtlGetFirstNode( pInfo->pListPads ); pNode; pNode = DtlGetNextNode( pNode )) { TCHAR* psz; psz = (TCHAR* )DtlGetData( pNode ); nIndex = ComboBox_AddString( pInfo->hwndLbX25Pads, psz ); if (pEntry->pszX25Network && lstrcmp( psz, pEntry->pszX25Network ) == 0) { ComboBox_SetCurSel( pInfo->hwndLbX25Pads, nIndex ); } } if (pEntry->pszX25Network && ComboBox_GetCurSel( pInfo->hwndLbX25Pads ) == 0) { /* PAD from phonebook is not in the PAD list. Add it and select ** it. */ nIndex = ComboBox_AddString( pInfo->hwndLbX25Pads, pEntry->pszX25Network ); ComboBox_SetCurSel( pInfo->hwndLbX25Pads, nIndex ); } } ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbX25Pads ); } BOOL XsInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { PEINFO* pInfo; PBENTRY* pEntry; BOOL fLocalPad; TRACE("XsInit"); pInfo = PeContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndXs = hwndPage; pInfo->hwndLbX25Pads = GetDlgItem( hwndPage, CID_XS_LB_Network ); ASSERT(pInfo->hwndLbX25Pads); pInfo->hwndEbX25Address = GetDlgItem( hwndPage, CID_XS_EB_Address ); ASSERT(pInfo->hwndEbX25Address); pInfo->hwndEbX25UserData = GetDlgItem( hwndPage, CID_XS_EB_UserData ); ASSERT(pInfo->hwndEbX25UserData); pInfo->hwndEbX25Facilities = GetDlgItem( hwndPage, CID_XS_EB_Facilities ); ASSERT(pInfo->hwndEbX25Facilities); /* Initialize page. */ pEntry = pInfo->pArgs->pEntry; fLocalPad = IsLocalPad( pEntry ); XsFillPadsList( pInfo, fLocalPad ); Edit_LimitText( pInfo->hwndEbX25Address, RAS_MaxX25Address ); if (pEntry->pszX25Address) SetWindowText( pInfo->hwndEbX25Address, pEntry->pszX25Address ); Edit_LimitText( pInfo->hwndEbX25UserData, RAS_MaxUserData ); if (pEntry->pszX25UserData) SetWindowText( pInfo->hwndEbX25UserData, pEntry->pszX25UserData ); Edit_LimitText( pInfo->hwndEbX25Facilities, RAS_MaxFacilities ); if (pEntry->pszX25Facilities) SetWindowText( pInfo->hwndEbX25Facilities, pEntry->pszX25Facilities ); if (fLocalPad) { /* No point in setting focus to "X.25 Network" on local PAD, so set to ** X.25 Address field instead. */ SetFocus( pInfo->hwndEbX25Address ); Edit_SetSel( pInfo->hwndEbX25Address, 0, -1 ); return FALSE; } return TRUE; } /*---------------------------------------------------------------------------- ** (Router) Dialing property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK RdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the router-specific dialing page of the Entry ** property sheet. Parameters and return value are as described for ** standard windows 'DialogProc's. */ { #if 0 TRACE4("RdDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return RdInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext(hwnd); if (pInfo) { ContextHelpHack( g_adwBsHelp, hwnd, unMsg, wparam, lparam, pInfo->pArgs->fRouter); } } break; case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); return RdCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } } return FALSE; } BOOL RdCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("RdCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_RD_RB_Persistent: case CID_RD_RB_DemandDial: { BOOL fDemandDial; fDemandDial = (wId == CID_RD_RB_DemandDial); EnableWindow( pInfo->hwndStIdle, fDemandDial ); EnableWindow( pInfo->hwndEbIdle, fDemandDial ); return TRUE; } case CID_RD_PB_Callback: { RouterCallbackDlg( pInfo->hwndRd, pInfo->pArgs ); return TRUE; } case CID_RD_PB_MultipleLines: { MultiLinkDialingDlg( pInfo->hwndRd, pInfo->pArgs->pEntry ); return TRUE; } } return FALSE; } BOOL RdInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { PEINFO* pInfo; PBENTRY* pEntry; HWND hwndUdAttempts; HWND hwndUdSeconds; HWND hwndUdIdle; TRACE("RdInit"); pInfo = PeContext( hwndPage ); if (!pInfo) return TRUE; pEntry = pInfo->pArgs->pEntry; ASSERT(pEntry); pInfo->hwndRd = hwndPage; pInfo->hwndRbPersistent = GetDlgItem( hwndPage, CID_RD_RB_Persistent ); ASSERT(pInfo->hwndRbPersistent); pInfo->hwndRbDemand = GetDlgItem( hwndPage, CID_RD_RB_DemandDial ); ASSERT(pInfo->hwndRbDemand); pInfo->hwndStAttempts = GetDlgItem( hwndPage, CID_RD_ST_Attempts ); ASSERT(pInfo->hwndStAttempts); pInfo->hwndEbAttempts = GetDlgItem( hwndPage, CID_RD_EB_Attempts ); ASSERT(pInfo->hwndEbAttempts); pInfo->hwndStSeconds = GetDlgItem( hwndPage, CID_RD_ST_Seconds ); ASSERT(pInfo->hwndStSeconds); pInfo->hwndEbSeconds = GetDlgItem( hwndPage, CID_RD_EB_Seconds ); ASSERT(pInfo->hwndEbSeconds); pInfo->hwndStIdle = GetDlgItem( hwndPage, CID_RD_ST_Idle ); ASSERT(pInfo->hwndStIdle); pInfo->hwndEbIdle = GetDlgItem( hwndPage, CID_RD_EB_Idle ); ASSERT(pInfo->hwndEbIdle); /* Initialize spin-button edit fields. */ hwndUdAttempts = CreateUpDownControl( WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT + UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS, 0, 0, 0, 0, hwndPage, 100, g_hinstDll, pInfo->hwndEbAttempts, UD_MAXVAL, 0, 0 ); ASSERT(hwndUdAttempts); Edit_LimitText( pInfo->hwndEbAttempts, 9 ); SetDlgItemInt( hwndPage, CID_RD_EB_Attempts, pEntry->dwRedialAttempts, FALSE ); hwndUdSeconds = CreateUpDownControl( WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT + UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS, 0, 0, 0, 0, hwndPage, 101, g_hinstDll, pInfo->hwndEbSeconds, UD_MAXVAL, 0, 0 ); ASSERT(hwndUdSeconds); Edit_LimitText( pInfo->hwndEbSeconds, 9 ); SetDlgItemInt( hwndPage, CID_RD_EB_Seconds, pEntry->dwRedialSeconds, FALSE ); hwndUdIdle = CreateUpDownControl( WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT + UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS, 0, 0, 0, 0, hwndPage, 102, g_hinstDll, pInfo->hwndEbIdle, UD_MAXVAL, 0, 0 ); ASSERT(hwndUdIdle); Edit_LimitText( pInfo->hwndEbIdle, 9 ); SetDlgItemInt( hwndPage, CID_RD_EB_Idle, pEntry->dwIdleDisconnectSeconds, FALSE ); /* Select the correct dialing option, triggering appropriate ** enabling/disabling. */ { HWND hwndRb; if (pEntry->fRedialOnLinkFailure) hwndRb = pInfo->hwndRbPersistent; else hwndRb = pInfo->hwndRbDemand; SendMessage( hwndRb, BM_CLICK, 0, 0 ); } return TRUE; } /*---------------------------------------------------------------------------- ** Before Dial dialog ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ BOOL BeforeDialDlg( IN HWND hwndOwner, IN OUT EINFO* pEinfo ) /* Pops-up the Before Dial scripting dialog. Initial settings are read ** from the working entry in common entry context 'pEinfo' and the result ** of user's edits written there on "OK" exit. The common entry context ** scripts list is refreshed by this routine. 'HwndOwner' is the window ** owning the dialog. ** ** Returns true if user pressed OK and succeeded, false if he pressed ** Cancel or encountered an error. */ { int nStatus; TRACE("BeforeDialDlg"); nStatus = (BOOL )DialogBoxParam( g_hinstDll, (pEinfo->fRouter) ? MAKEINTRESOURCE( DID_BD_RouterBeforeDial ) : MAKEINTRESOURCE( DID_BD_BeforeDial ), hwndOwner, BdDlgProc, (LPARAM )pEinfo ); if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; } return (BOOL )nStatus; } INT_PTR CALLBACK BdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Before Dial dialog. Parameters and return ** value are as described for standard windows 'DialogProc's. */ { #if 0 TRACE4("BdDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return BdInit( hwnd, (EINFO* )lparam ); case WM_HELP: case WM_CONTEXTMENU: ContextHelpHack( g_adwBdHelp, hwnd, unMsg, wparam, lparam, ((BDINFO *)GetWindowLongPtr(hwnd, DWLP_USER))->pArgs->fRouter); break; case WM_COMMAND: { BDINFO* pInfo = (BDINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo); return BdCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } case WM_DESTROY: { BdTerm( hwnd ); break; } } return FALSE; } BOOL BdCommand( IN BDINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("BdCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_BD_PB_Refresh: { INT iSel; TCHAR* pszSel; iSel = ComboBox_GetCurSel( pInfo->hwndLbScript ); if (iSel > 0) pszSel = ComboBox_GetPsz( pInfo->hwndLbScript, iSel ); else pszSel = NULL; EuFillScriptsList( pInfo->pArgs, pInfo->hwndLbScript, pszSel ); Free0( pszSel ); return TRUE; } case CID_BD_PB_Edit: { EuEditSwitchInf( pInfo->hwndDlg ); return TRUE; } case CID_BD_RB_None: case CID_BD_RB_Terminal: case CID_BD_RB_Script: { /* Scripts listbox is gray unless script mode is selected. */ if (wNotification == BN_CLICKED) EnableWindow( pInfo->hwndLbScript, (wId == CID_BD_RB_Script) ); break; } case IDOK: { TRACE("OK pressed"); BdSave( pInfo ); EndDialog( pInfo->hwndDlg, TRUE ); return TRUE; } case IDCANCEL: { TRACE("Cancel pressed"); EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; } } return FALSE; } BOOL BdInit( IN HWND hwndDlg, IN EINFO* pArgs ) /* Called on WM_INITDIALOG. 'hwndDlg' is the handle of the phonebook ** dialog window. 'pArgs' is caller's argument to the stub API. ** ** Return false if focus was set, true otherwise, i.e. as defined for ** WM_INITDIALOG. */ { DWORD dwErr; BDINFO* pInfo; TRACE("BdInit"); /* 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; SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo ); TRACE("Context set"); } pInfo->hwndRbNone = GetDlgItem( hwndDlg, CID_BD_RB_None ); ASSERT(pInfo->hwndRbNone); pInfo->hwndRbTerminal = GetDlgItem( hwndDlg, CID_BD_RB_Terminal ); ASSERT(pInfo->hwndRbTerminal); pInfo->hwndRbScript = GetDlgItem( hwndDlg, CID_BD_RB_Script ); ASSERT(pInfo->hwndRbScript); pInfo->hwndLbScript = GetDlgItem( hwndDlg, CID_BD_LB_Script ); ASSERT(pInfo->hwndLbScript); pInfo->hwndPbEdit = GetDlgItem( hwndDlg, CID_BD_PB_Edit ); ASSERT(pInfo->hwndPbEdit); pInfo->hwndPbRefresh = GetDlgItem( hwndDlg, CID_BD_PB_Refresh ); ASSERT(pInfo->hwndPbRefresh); /* Fill list boxes and set the selection. */ EuFillScriptsList( pInfo->pArgs, pInfo->hwndLbScript, pInfo->pArgs->pEntry->pszScriptBefore ); /* Select the correct modes. */ { HWND hwndRb; DWORD dwScriptMode; dwScriptMode = pArgs->pEntry->dwScriptModeBefore; if (dwScriptMode == SM_Terminal && !pArgs->fRouter) hwndRb = pInfo->hwndRbTerminal; else if (dwScriptMode == SM_Script) hwndRb = pInfo->hwndRbScript; else hwndRb = pInfo->hwndRbNone; SendMessage( hwndRb, BM_CLICK, 0, 0 ); } /* Center dialog on the owner window. */ CenterWindow( hwndDlg, GetParent( hwndDlg ) ); return TRUE; } VOID BdSave( IN BDINFO* pInfo ) /* Saves dialog settings in the entry. 'PInfo' is the dialog context. */ { INT iSel; PBENTRY* pEntry; TRACE("BdSave"); pEntry = pInfo->pArgs->pEntry; ASSERT(pEntry); if (IsDlgButtonChecked( pInfo->hwndDlg, CID_BD_RB_None )) pEntry->dwScriptModeBefore = SM_None; else if (IsDlgButtonChecked( pInfo->hwndDlg, CID_BD_RB_Terminal )) pEntry->dwScriptModeBefore = SM_Terminal; else pEntry->dwScriptModeBefore = SM_Script; iSel = ComboBox_GetCurSel( pInfo->hwndLbScript ); Free0( pEntry->pszScriptBefore ); if (iSel > 0) pEntry->pszScriptBefore = ComboBox_GetPsz( pInfo->hwndLbScript, iSel ); else pEntry->pszScriptBefore = NULL; /* Silently fix-up "no script specified" error. */ if (pEntry->dwScriptModeBefore == SM_Script && !pEntry->pszScriptBefore) pEntry->dwScriptModeBefore = SM_None; pEntry->fDirty = TRUE; } VOID BdTerm( IN HWND hwndDlg ) /* Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window. */ { BDINFO* pInfo = (BDINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER ); TRACE("BdTerm"); if (pInfo) Free( pInfo ); } /*---------------------------------------------------------------------------- ** (Router) Callback dialog ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ BOOL RouterCallbackDlg( IN HWND hwndOwner, IN OUT EINFO* pEinfo ) /* Pops-up the (Router) Callback dialog. Initial settings are read from ** the working entry (no/yes choice) and router user preferences (number ** list) in common entry context 'pEinfo' and the result of user's edits ** written there on "OK" exit. 'HwndOwner' is the window owning the ** dialog. ** ** Returns true if user pressed OK and succeeded, false if he pressed ** Cancel or encountered an error. */ { int nStatus; TRACE("RouterCallbackDlg"); nStatus = (BOOL )DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( DID_CR_CallbackRouter ), hwndOwner, CrDlgProc, (LPARAM )pEinfo ); if (nStatus == -1) { ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; } return (BOOL )nStatus; } INT_PTR CALLBACK CrDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the (Router) Callback dialog. Parameters and ** return value are as described for standard windows 'DialogProc's. */ { #if 0 TRACE4("CrDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif if (ListView_OwnerHandler( hwnd, unMsg, wparam, lparam, CbutilLvNumbersCallback )) { return TRUE; } switch (unMsg) { case WM_INITDIALOG: return CrInit( hwnd, (EINFO* )lparam ); case WM_HELP: case WM_CONTEXTMENU: ContextHelpHack( g_adwCrHelp, hwnd, unMsg, wparam, lparam, ((CRINFO *)GetWindowLongPtr(hwnd, DWLP_USER))->pArgs->fRouter); break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case NM_DBLCLK: { CRINFO* pInfo = (CRINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo); SendMessage( pInfo->hwndPbEdit, BM_CLICK, 0, 0 ); return TRUE; } case LVN_ITEMCHANGED: { CRINFO* pInfo = (CRINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo); CrUpdateLvAndPbState( pInfo ); return TRUE; } } break; } case WM_COMMAND: { CRINFO* pInfo = (CRINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo); return CrCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } case WM_DESTROY: { CrTerm( hwnd ); break; } } return FALSE; } BOOL CrCommand( IN CRINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ) /* Called on WM_COMMAND. 'PInfo' is the dialog context. '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. */ { TRACE2("CrCommand(n=%d,i=%d)", (DWORD)wNotification,(DWORD)wId); switch (wId) { case CID_CR_RB_No: case CID_CR_RB_Yes: { if (wNotification == BN_CLICKED) { CrUpdateLvAndPbState( pInfo ); if (wId == CID_CR_RB_Yes && ListView_GetSelectedCount( pInfo->hwndLvNumbers ) == 0) { /* Nothing's selected, so select the first item, if any. */ ListView_SetItemState( pInfo->hwndLvNumbers, 0, LVIS_SELECTED, LVIS_SELECTED ); } } break; } case CID_CR_PB_Edit: { if (wNotification == BN_CLICKED) CbutilEdit( pInfo->hwndDlg, pInfo->hwndLvNumbers ); break; } case CID_CR_PB_Delete: { if (wNotification == BN_CLICKED) CbutilDelete( pInfo->hwndDlg, pInfo->hwndLvNumbers ); break; } case IDOK: { TRACE("OK pressed"); CrSave( pInfo ); EndDialog( pInfo->hwndDlg, TRUE ); return TRUE; } case IDCANCEL: { TRACE("Cancel pressed"); EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; } } return FALSE; } BOOL CrInit( IN HWND hwndDlg, IN EINFO* pArgs ) /* Called on WM_INITDIALOG. 'hwndDlg' is the handle of the phonebook ** dialog window. 'pArgs' is caller's argument to the stub API. ** ** Return false if focus was set, true otherwise, i.e. as defined for ** WM_INITDIALOG. */ { DWORD dwErr; CRINFO* pInfo; TRACE("CrInit"); /* 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; SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo ); TRACE("Context set"); } /* Initialize page-specific context information. */ pInfo->hwndRbNo = GetDlgItem( hwndDlg, CID_CR_RB_No ); ASSERT(pInfo->hwndRbNo); pInfo->hwndRbYes = GetDlgItem( hwndDlg, CID_CR_RB_Yes ); ASSERT(pInfo->hwndRbYes); pInfo->hwndLvNumbers = GetDlgItem( hwndDlg, CID_CR_LV_Numbers ); ASSERT(pInfo->hwndLvNumbers); pInfo->hwndPbEdit = GetDlgItem( hwndDlg, CID_CR_PB_Edit ); ASSERT(pInfo->hwndPbEdit); pInfo->hwndPbDelete = GetDlgItem( hwndDlg, CID_CR_PB_Delete ); ASSERT(pInfo->hwndPbDelete); /* Initialize the listview. */ CbutilFillLvNumbers( pInfo->hwndDlg, pInfo->hwndLvNumbers, pArgs->pUser->pdtllistCallback, pArgs->fRouter ); /* Set the radio button selection, which triggers appropriate ** enabling/disabling. */ { HWND hwndRb; if (pArgs->pEntry->dwCallbackMode == CBM_No) hwndRb = pInfo->hwndRbNo; else { ASSERT(pArgs->pEntry->dwCallbackMode==CBM_Yes); hwndRb = pInfo->hwndRbYes; } SendMessage( hwndRb, BM_CLICK, 0, 0 ); } /* Center dialog on the owner window. */ CenterWindow( hwndDlg, GetParent( hwndDlg ) ); return TRUE; } VOID CrSave( IN CRINFO* pInfo ) /* Saves dialog settings in the entry. 'PInfo' is the dialog context. */ { PBENTRY* pEntry; TRACE("CrSave"); pEntry = pInfo->pArgs->pEntry; ASSERT(pEntry); if (IsDlgButtonChecked( pInfo->hwndDlg, CID_CR_RB_No )) pEntry->dwCallbackMode = CBM_No; else pEntry->dwCallbackMode = CBM_Yes; pEntry->dwfOverridePref |= RASOR_CallbackMode; pEntry->fDirty = TRUE; CbutilSaveLv( pInfo->hwndLvNumbers, pInfo->pArgs->pUser->pdtllistCallback ); } VOID CrTerm( IN HWND hwndDlg ) /* Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window. */ { CRINFO* pInfo = (CRINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER ); TRACE("CrTerm"); if (pInfo) Free( pInfo ); } VOID CrUpdateLvAndPbState( IN CRINFO* pInfo ) /* Enables/disables the list view and associated buttons. ListView is ** gray unless auto-callback is selected. Buttons gray unless ** auto-callback selected and there is an item selected. */ { BOOL fEnableList; BOOL fEnableButton; fEnableList = Button_GetCheck( pInfo->hwndRbYes ); if (fEnableList) { fEnableButton = ListView_GetSelectedCount( pInfo->hwndLvNumbers ); } else fEnableButton = FALSE; EnableWindow( pInfo->hwndLvNumbers, fEnableList ); EnableWindow( pInfo->hwndPbEdit, fEnableButton ); EnableWindow( pInfo->hwndPbDelete, fEnableButton ); } /*----------------------------------------------------- ** Utilities shared with router version of the listview **----------------------------------------------------- */ VOID CbutilDelete( IN HWND hwndDlg, IN HWND hwndLvNumbers ) /* Called when the Delete button is pressed. 'PInfo' is the dialog ** context. */ { MSGARGS msgargs; INT nResponse; TRACE("CbDelete"); ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_YESNO + MB_ICONEXCLAMATION; nResponse = MsgDlg( hwndDlg, SID_ConfirmDelDevice, &msgargs ); if (nResponse == IDYES) { INT iSel; /* User has confirmed deletion of selected devices, so do it. */ while ((iSel = ListView_GetNextItem( hwndLvNumbers, -1, LVNI_SELECTED )) >= 0) { ListView_DeleteItem( hwndLvNumbers, iSel ); } } } VOID CbutilEdit( IN HWND hwndDlg, IN HWND hwndLvNumbers ) /* Called when the Edit button is pressed. 'HwndDlg' is the page/dialog ** window. 'HwndLvNumbers' is the callback number listview window. */ { INT iSel; TCHAR szBuf[ RAS_MaxCallbackNumber + 1 ]; TCHAR* pszNumber; TRACE("CbutilEdit"); /* Load 'szBuf' with the current phone number of the first selected item. */ iSel = ListView_GetNextItem( hwndLvNumbers, -1, LVNI_SELECTED ); if (iSel < 0) return; szBuf[ 0 ] = TEXT('\0'); ListView_GetItemText( hwndLvNumbers, iSel, 1, szBuf, RAS_MaxCallbackNumber + 1 ); /* Popup dialog to edit the number. */ pszNumber = NULL; if (StringEditorDlg( hwndDlg, szBuf, SID_EcbnTitle, SID_EcbnLabel, RAS_MaxCallbackNumber, HID_ZE_ST_CallbackNumber, &pszNumber )) { /* OK pressed, so change the number on all selected items. */ ASSERT(pszNumber); do { ListView_SetItemText( hwndLvNumbers, iSel, 1, pszNumber ); } while ((iSel = ListView_GetNextItem( hwndLvNumbers, iSel, LVNI_SELECTED )) >= 0); } } VOID CbutilFillLvNumbers( IN HWND hwndDlg, IN HWND hwndLvNumbers, IN DTLLIST* pListCallback, IN BOOL fRouter ) /* Fill the listview with devices and phone numbers. 'HwndDlg' is the ** page/dialog window. 'HwndLvNumbers' is the callback listview. ** 'PListCallback' is the list of CALLBACKINFO. 'FRouter' is true if the ** router ports should be enumerated, or false for regular dial-out ports. ** ** Note: This routine should be called only once. */ { DWORD dwErr; DTLLIST* pListPorts; DTLNODE* pNodeCbi; DTLNODE* pNodePort; INT iItem; TCHAR* psz; TRACE("CbutilFillLvNumbers"); ListView_DeleteAllItems( hwndLvNumbers ); /* Add columns. */ { LV_COLUMN col; TCHAR* pszHeader0; TCHAR* pszHeader1; pszHeader0 = PszFromId( g_hinstDll, SID_DeviceColHead ); pszHeader1 = PszFromId( g_hinstDll, SID_PhoneNumberColHead ); ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT + LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.pszText = (pszHeader0) ? pszHeader0 : TEXT(""); ListView_InsertColumn( hwndLvNumbers, 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( hwndLvNumbers, 1, &col ); Free0( pszHeader0 ); Free0( pszHeader1 ); } /* Add the modem and adapter images. */ ListView_SetDeviceImageList( hwndLvNumbers, g_hinstDll ); /* Load listview with callback device/number pairs saved as user ** preferences. */ iItem = 0; ASSERT(pListCallback); for (pNodeCbi = DtlGetFirstNode( pListCallback ); pNodeCbi; pNodeCbi = DtlGetNextNode( pNodeCbi ), ++iItem) { CALLBACKINFO* pCbi; LV_ITEM item; pCbi = (CALLBACKINFO* )DtlGetData( pNodeCbi ); ASSERT(pCbi); ASSERT(pCbi->pszPortName); ASSERT(pCbi->pszDeviceName); ASSERT(pCbi->pszNumber); psz = PszFromDeviceAndPort( pCbi->pszDeviceName, pCbi->pszPortName ); if (psz) { ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM; item.iItem = iItem; item.pszText = psz; item.iImage = ((PBDEVICETYPE )pCbi->dwDeviceType == PBDT_Modem) ? DI_Modem : DI_Adapter; item.lParam = (LPARAM )pCbi->dwDeviceType; ListView_InsertItem( hwndLvNumbers, &item ); ListView_SetItemText( hwndLvNumbers, iItem, 1, pCbi->pszNumber ); Free( psz ); } } /* Add any devices installed but not already in the list. */ dwErr = LoadPortsList2( &pListPorts, fRouter ); if (dwErr != 0) { ErrorDlg( hwndDlg, SID_OP_LoadPortInfo, dwErr, NULL ); } else { for (pNodePort = DtlGetFirstNode( pListPorts ); pNodePort; pNodePort = DtlGetNextNode( pNodePort )) { PBPORT* pPort = (PBPORT* )DtlGetData( pNodePort ); ASSERT(pPort); /* Look for the device/port in the callback list. */ for (pNodeCbi = DtlGetFirstNode( pListCallback ); pNodeCbi; pNodeCbi = DtlGetNextNode( pNodeCbi )) { CALLBACKINFO* pCbi; LV_ITEM item; pCbi = (CALLBACKINFO* )DtlGetData( pNodeCbi ); ASSERT(pCbi); ASSERT(pCbi->pszPortName); ASSERT(pCbi->pszDeviceName); if (lstrcmpi( pPort->pszPort, pCbi->pszPortName ) == 0 && lstrcmpi( pPort->pszDevice, pCbi->pszDeviceName ) == 0) { break; } } if (!pNodeCbi) { LV_ITEM item; PBDEVICETYPE pbdt; /* The device/port was not in the callback list. Append it to ** the listview with empty phone number. */ psz = PszFromDeviceAndPort( pPort->pszDevice, pPort->pszPort ); if (psz) { ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM; item.iItem = iItem; item.pszText = psz; item.iImage = (pPort->pbdevicetype == PBDT_Modem) ? DI_Modem : DI_Adapter; item.lParam = (LPARAM )pPort->pbdevicetype; ListView_InsertItem( hwndLvNumbers, &item ); ListView_SetItemText( hwndLvNumbers, iItem, 1, TEXT("") ); ++iItem; Free( psz ); } } } DtlDestroyList( pListPorts, DestroyPortNode ); } /* Auto-size columns to look good with the text they contain. */ ListView_SetColumnWidth( hwndLvNumbers, 0, LVSCW_AUTOSIZE_USEHEADER ); ListView_SetColumnWidth( hwndLvNumbers, 1, LVSCW_AUTOSIZE_USEHEADER ); } LVXDRAWINFO* CbutilLvNumbersCallback( 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_Blend50Dis + LVXDI_DxFill, { 0, 0 } }; return &info; } VOID CbutilSaveLv( IN HWND hwndLvNumbers, OUT DTLLIST* pListCallback ) /* Replace list 'pListCallback' contents with that of the listview ** 'hwndLvNumbers'. */ { DTLNODE* pNode; INT i; TRACE("CbutilSaveLv"); /* Empty the list of callback info, then re-populate from the listview. */ while (pNode = DtlGetFirstNode( pListCallback )) { DtlRemoveNode( pListCallback, pNode ); DestroyCallbackNode( pNode ); } i = -1; while ((i = ListView_GetNextItem( hwndLvNumbers, i, LVNI_ALL )) >= 0) { LV_ITEM item; TCHAR* pszDevice; TCHAR* pszPort; TCHAR szDP[ RAS_MaxDeviceName + 2 + MAX_PORT_NAME + 1 + 1 ]; TCHAR szNumber[ RAS_MaxCallbackNumber + 1 ]; szDP[ 0 ] = TEXT('\0'); ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = i; item.pszText = szDP; item.cchTextMax = sizeof(szDP) / sizeof(TCHAR); if (!ListView_GetItem( hwndLvNumbers, &item )) continue; szNumber[ 0 ] = TEXT('\0'); ListView_GetItemText( hwndLvNumbers, i, 1, szNumber, RAS_MaxCallbackNumber + 1 ); if (!DeviceAndPortFromPsz( szDP, &pszDevice, &pszPort )) continue; pNode = CreateCallbackNode( pszPort, pszDevice, szNumber, (DWORD )item.lParam ); if (pNode) DtlAddNodeLast( pListCallback, pNode ); Free( pszDevice ); Free( pszPort ); } }