// 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" #include "entryps.h" #include "uiinfo.h" #include "inetcfgp.h" #include "netcon.h" #include "rassrvrc.h" #include "shlobjp.h" #include "shellapi.h" #include "iphlpapi.h" #include "prsht.h" #include "pbkp.h" // Page definitions. // #define PE_GePage 0 #define PE_OePage 1 #define PE_LoPage 2 #define PE_NePage 3 #define PE_SaPage 4 #define PE_PageCount 5 // (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; }; static TCHAR g_pszFirewallRegKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\HomeNetworking\\PersonalFirewall"); static TCHAR g_pszDisableFirewallWarningValue[] = TEXT("ShowDisableFirewallWarning"); //---------------------------------------------------------------------------- // Help maps //---------------------------------------------------------------------------- static const DWORD g_adwGeHelp[] = { CID_GE_GB_ConnectUsing, HID_GE_LV_Device, //HID_GE_GB_ConnectUsing, CID_GE_LV_Device, HID_GE_LV_Device, CID_GE_LV_Devices, HID_GE_LV_Devices, CID_GE_PB_MoveUp, HID_GE_PB_MoveUp, CID_GE_PB_MoveDown, HID_GE_PB_MoveDown, CID_GE_CB_SharedPhoneNumber, HID_GE_CB_SharedPhoneNumber, CID_GE_PB_Configure, HID_GE_PB_Configure, CID_GE_ST_AreaCodes, HID_GE_CLB_AreaCodes, CID_GE_CLB_AreaCodes, HID_GE_CLB_AreaCodes, CID_GE_ST_PhoneNumber, HID_GE_EB_PhoneNumber, CID_GE_EB_PhoneNumber, HID_GE_EB_PhoneNumber, CID_GE_ST_CountryCodes, HID_GE_LB_CountryCodes, CID_GE_LB_CountryCodes, HID_GE_LB_CountryCodes, CID_GE_CB_UseDialingRules, HID_GE_CB_UseDialingRules, CID_GE_PB_Alternates, HID_GE_PB_Alternates, CID_GE_CB_ShowIcon, HID_GE_CB_ShowIcon, CID_GE_ST_HostName, HID_GE_EB_HostName, CID_GE_EB_HostName, HID_GE_EB_HostName, CID_GE_ST_ServiceName, HID_GE_EB_ServiceName, //Add for whistler bug 343249 CID_GE_EB_ServiceName, HID_GE_EB_ServiceName, CID_GE_GB_FirstConnect, -1, //HID_GE_GB_FirstConnect, CID_GE_ST_Explain, HID_GE_GB_FirstConnect, CID_GE_CB_DialAnotherFirst, HID_GE_CB_DialAnotherFirst, CID_GE_LB_DialAnotherFirst, HID_GE_LB_DialAnotherFirst, CID_GE_ST_Devices, HID_GE_LB_Devices, CID_GE_LB_Devices, HID_GE_LB_Devices, CID_GE_PB_DialingRules, HID_GE_PB_DialingRules, CID_GE_GB_PhoneNumber, -1, 0, 0 }; static const DWORD g_adwOeHelp[] = { CID_OE_GB_Progress, -1, //commented for bug 15738//HID_OE_GB_Progress, CID_OE_CB_DisplayProgress, HID_OE_CB_DisplayProgress, CID_OE_CB_PreviewUserPw, HID_OE_CB_PreviewUserPw, CID_OE_CB_PreviewDomain, HID_OE_CB_PreviewDomain, CID_OE_CB_PreviewNumber, HID_OE_CB_PreviewNumber, CID_OE_GB_Redial, -1, //commented for bug 15738//HID_OE_GB_Redial, CID_OE_ST_RedialAttempts, HID_OE_EB_RedialAttempts, CID_OE_EB_RedialAttempts, HID_OE_EB_RedialAttempts, CID_OE_ST_RedialTimes, HID_OE_LB_RedialTimes, CID_OE_LB_RedialTimes, HID_OE_LB_RedialTimes, CID_OE_ST_IdleTimes, HID_OE_LB_IdleTimes, CID_OE_LB_IdleTimes, HID_OE_LB_IdleTimes, CID_OE_CB_RedialOnDrop, HID_OE_CB_RedialOnDrop, CID_OE_GB_MultipleDevices, -1, //commented for bug 15738//HID_OE_GB_MultipleDevices, CID_OE_LB_MultipleDevices, HID_OE_LB_MultipleDevices, CID_OE_PB_Configure, HID_OE_PB_Configure, CID_OE_PB_X25, HID_OE_PB_X25, CID_OE_PB_Tunnel, HID_OE_PB_Tunnel, CID_OE_RB_DemandDial, HID_OE_RB_DemandDial, CID_OE_RB_Persistent, HID_OE_RB_Persistent, 0, 0 }; static const DWORD g_adwOeRouterHelp[] = { CID_OE_GB_Progress, -1, //commented for bug 15738//HID_OE_GB_Progress, CID_OE_CB_DisplayProgress, HID_OE_CB_DisplayProgress, CID_OE_CB_PreviewUserPw, HID_OE_CB_PreviewUserPw, CID_OE_CB_PreviewDomain, HID_OE_CB_PreviewDomain, CID_OE_CB_PreviewNumber, HID_OE_CB_PreviewNumber, CID_OE_GB_Redial, -1, //commented for bug 15738//HID_OE_GB_Redial, CID_OE_ST_RedialAttempts, HID_OE_EB_RedialAttempts, CID_OE_EB_RedialAttempts, HID_OE_EB_RedialAttempts, CID_OE_ST_RedialTimes, HID_OE_LB_RedialTimes, CID_OE_LB_RedialTimes, HID_OE_LB_RedialTimes, CID_OE_ST_IdleTimes, HID_OE_LB_IdleTimesRouter, CID_OE_LB_IdleTimes, HID_OE_LB_IdleTimesRouter, CID_OE_CB_RedialOnDrop, HID_OE_CB_RedialOnDrop, CID_OE_GB_MultipleDevices, -1, //commented for bug 15738//HID_OE_GB_MultipleDevices, CID_OE_LB_MultipleDevices, HID_OE_LB_MultipleDevices, CID_OE_PB_Configure, HID_OE_PB_Configure, CID_OE_PB_X25, HID_OE_PB_X25, CID_OE_PB_Tunnel, HID_OE_PB_Tunnel, CID_OE_RB_DemandDial, HID_OE_RB_DemandDial, CID_OE_RB_Persistent, HID_OE_RB_Persistent, CID_OE_PB_Callback, HID_OE_PB_Callback, 0, 0 }; //Get rid of the const qualifire for whistler bug#276452 static DWORD g_adwLoHelp[] = { CID_LO_GB_SecurityOptions, -1, //commented for bug 15738//HID_LO_GB_SecurityOptions, CID_LO_RB_TypicalSecurity, HID_LO_RB_TypicalSecurity, CID_LO_ST_Auths, HID_LO_LB_Auths, CID_LO_LB_Auths, HID_LO_LB_Auths, CID_LO_CB_UseWindowsPw, HID_LO_CB_UseWindowsPw, CID_LO_CB_Encryption, HID_LO_CB_Encryption, CID_LO_RB_AdvancedSecurity, HID_LO_RB_AdvancedSecurity, CID_LO_ST_AdvancedText, HID_LO_PB_Advanced, CID_LO_PB_Advanced, HID_LO_PB_Advanced, CID_LO_GB_Scripting, -1, //commented for bug 15738//HID_LO_GB_Scripting, CID_LO_CB_RunScript, HID_LO_CB_RunScript, CID_LO_CB_Terminal, HID_LO_CB_Terminal, CID_LO_LB_Scripts, HID_LO_LB_Scripts, CID_LO_PB_Edit, HID_LO_PB_Edit, CID_LO_PB_Browse, HID_LO_PB_Browse, CID_LO_ST_IPSecText, HID_LO_PB_IPSec, CID_LO_PB_IPSec, HID_LO_PB_IPSec,//On Server, this help ID will be HID_LO_PB_IPSecServer 0, 0 }; static const DWORD g_adwNeHelp[] = { CID_NE_ST_ServerType, HID_NE_LB_ServerType, CID_NE_LB_ServerType, HID_NE_LB_ServerType, CID_NE_PB_Settings, HID_NE_PB_Settings, CID_NE_ST_Components, HID_NE_LV_Components, CID_NE_LV_Components, HID_NE_LV_Components, CID_NE_PB_Add, HID_NE_PB_Add, CID_NE_PB_Remove, HID_NE_PB_Remove, CID_NE_PB_Properties, HID_NE_PB_Properties, CID_NE_GB_Description, -1, //commented for bug 15738//HID_NE_LB_ComponentDesc, CID_NE_LB_ComponentDesc, HID_NE_LB_ComponentDesc, 0, 0 }; static const DWORD g_adwPpHelp[] = { CID_NE_EnableLcp, HID_NE_EnableLcp, CID_NE_EnableCompression, HID_NE_EnableCompression, CID_NE_NegotiateMultilinkAlways,HID_NE_NegotiateMultilinkAlways, 0, 0 }; static DWORD g_adwCrHelp[] = { CID_CR_RB_No, HID_CR_RB_No, CID_CR_RB_Yes, HID_CR_RB_Yes, CID_CR_PB_Edit, HID_CR_PB_Edit, CID_CR_PB_Delete, HID_CR_PB_Delete, CID_CR_LV_Numbers, HID_CR_LV_Numbers, 0, 0 }; static DWORD g_adwSaHelp[] = { CID_SA_PB_Shared, HID_SA_PB_Shared, CID_SA_GB_Shared, -1, CID_SA_PB_DemandDial, HID_SA_PB_DemandDial, CID_SA_ST_DemandDial, HID_SA_PB_DemandDial, CID_SA_PB_Settings, HID_SA_PB_Settings, CID_SA_GB_PrivateLan, -1, CID_SA_ST_PrivateLan, HID_SA_LB_PrivateLan, CID_SA_LB_PrivateLan, HID_SA_LB_PrivateLan, 0, 0 }; //----------------------------------------------------------------------------- // Local prototypes (alphabetically) //----------------------------------------------------------------------------- BOOL RouterCallbackDlg( IN HWND hwndOwner, IN OUT EINFO* pEinfo ); 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 ); VOID GeAlternates( IN PEINFO* pInfo ); VOID GeDialingRules( IN PEINFO* pInfo ); INT_PTR CALLBACK GeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); INT_PTR CALLBACK GeDlgProcMultiple( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); INT_PTR CALLBACK GeDlgProcSingle( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); VOID GeClearLbDialAnotherFirst( IN HWND hwndLbDialAnotherFirst ); BOOL GeCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); VOID GeConfigure( IN PEINFO* pInfo ); VOID GeDialAnotherFirstSelChange( IN PEINFO* pInfo ); BOOL GeFillLbDialAnotherFirst( IN PEINFO* pInfo, IN BOOL fAbortIfPrereqNotFound ); VOID GeGetPhoneFields( IN PEINFO* pInfo, OUT DTLNODE* pDstLinkNode ); BOOL GeInit( IN HWND hwndPage, IN OUT EINFO* pArgs ); LVXDRAWINFO* GeLvDevicesCallbackMultiple( IN HWND hwndLv, IN DWORD dwItem ); LVXDRAWINFO* GeLvDevicesCallbackSingle( IN HWND hwndLv, IN DWORD dwItem ); VOID GeMoveDevice( IN PEINFO* pInfo, IN BOOL fUp ); DWORD GeSaveLvDeviceChecks( IN PEINFO* pInfo ); VOID GeUpdateDialAnotherFirstState( IN PEINFO* pInfo ); VOID GeSetPhoneFields( IN PEINFO* pInfo, IN DTLNODE* pSrcLinkNode, IN BOOL fDisableAll ); VOID GeUpdatePhoneNumberFields( IN PEINFO* pInfo, IN BOOL fSharedToggle ); VOID GeUpdatePhoneNumberTitle( IN PEINFO* pInfo, IN TCHAR* pszDevice ); VOID GeUpdateUpDownButtons( IN PEINFO* pInfo ); BOOL LoCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK LoDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); VOID LoEnableSecuritySettings( IN PEINFO* pInfo, IN BOOL fTypical, IN BOOL fAdvanced ); VOID LoFillLbAuths( IN PEINFO* pInfo ); BOOL LoInit( IN HWND hwndPage ); VOID LoLbAuthsSelChange( IN PEINFO* pInfo ); VOID LoRefreshSecuritySettings( IN PEINFO* pInfo ); VOID LoSaveTypicalAuthSettings( IN PEINFO* pInfo ); INT_PTR CALLBACK NeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL NeInit( IN HWND hwndPage ); void NeServerTypeSelChange ( IN PEINFO* pInfo); void NeAddComponent ( IN PEINFO* pInfo); void NeEnsureNetshellLoaded ( IN PEINFO* pInfo); void NeRemoveComponent ( IN PEINFO* pInfo); void NeLvClick ( IN PEINFO* pInfo, IN BOOL fDoubleClick); void NeLvItemChanged ( IN PEINFO* pInfo); void NeSaveBindingChanges ( IN PEINFO* pInfo); void NeLvDeleteItem ( IN PEINFO* pInfo, IN NM_LISTVIEW* pnmlv); BOOL OeCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK OeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); VOID OeEnableMultipleDeviceGroup( IN PEINFO* pInfo, IN BOOL fEnable ); BOOL OeInit( IN HWND hwndPage ); VOID OeTunnel( IN PEINFO* pInfo ); VOID OeUpdateUserPwState( IN PEINFO* pInfo ); VOID OeX25( IN PEINFO* pInfo ); BOOL PeApply( 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, IN EINFO* pEinfo, IN DWORD dwError ); PEINFO* PeInit( IN HWND hwndFirstPage, IN EINFO* pArgs ); VOID PeTerm( IN HWND hwndPage ); INT_PTR CALLBACK PpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); INT_PTR CALLBACK RdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL SaCommand( IN PEINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK SaDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); INT_PTR CALLBACK SaUnavailDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL SaInit( IN HWND hwndDlg ); INT_PTR CALLBACK SaDisableFirewallWarningDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL SaIsAdapterDHCPEnabled( IN IHNetConnection* pConnection); // wrapper to load homenet page: used in PePropertySheet(...) HRESULT HrLoadHNetGetFirewallSettingsPage (PROPSHEETPAGEW * ppsp, EINFO* pInfo) { PROPSHEETPAGEW psp; HRESULT hr; HNET_CONN_PROPERTIES *pProps; IHNetConnection *pHNetConn = NULL; IHNetCfgMgr *pHNetCfgMgr = NULL; // _asm int 3 ZeroMemory (&psp, sizeof(PROPSHEETPAGEW)); psp.dwSize = sizeof(PROPSHEETPAGEW); *ppsp = psp; // Make sure COM is initialized on this thread. // hr = CoInitializeEx( NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE ); if (SUCCEEDED(hr)) { pInfo->fComInitialized = TRUE; } else if (RPC_E_CHANGED_MODE == hr) { hr = S_OK; } if (SUCCEEDED(hr)) { // pass the Guid to the export from hnetcfg ("HNetGetFirewallSettingsPage"). HINSTANCE hinstDll = LoadLibrary (TEXT("hnetcfg.dll")); if (hinstDll == NULL) hr = HRESULT_FROM_WIN32 (GetLastError()); else { HRESULT (*pfnGetPage) (PROPSHEETPAGEW *, GUID *); pfnGetPage = (HRESULT (*)(PROPSHEETPAGEW *, GUID *))GetProcAddress (hinstDll, "HNetGetFirewallSettingsPage"); if (!pfnGetPage) hr = HRESULT_FROM_WIN32 (GetLastError()); else hr = pfnGetPage (&psp, pInfo->pEntry->pGuid); FreeLibrary (hinstDll); } if (hr == S_OK) *ppsp = psp; } return pInfo->hShowHNetPagesResult = hr; } //---------------------------------------------------------------------------- // Phonebook Entry property sheet entrypoint //---------------------------------------------------------------------------- VOID PePropertySheet( IN OUT EINFO* pEinfo ) // Runs the Phonebook entry property sheet. 'PEinfo' is the API caller's // arguments. // { PROPSHEETPAGE apage[ PE_PageCount ]; PROPSHEETPAGE* ppage; INT nPages; INT nPageIndex; TRACE( "PePropertySheet" ); nPages = PE_PageCount; ZeroMemory( apage, sizeof(apage) ); // General page. // ppage = &apage[ PE_GePage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; if (pEinfo->pEntry->dwType == RASET_Vpn) { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_GeneralVpn ); ppage->pfnDlgProc = GeDlgProc; } else if (pEinfo->pEntry->dwType == RASET_Broadband) { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_GeneralBroadband ); ppage->pfnDlgProc = GeDlgProc; } else if (pEinfo->pEntry->dwType == RASET_Phone) { if (pEinfo->fMultipleDevices) { if (pEinfo->fRouter) { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_RouterGeneralMultiple ); } else { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_GeneralMultiple ); } ppage->pfnDlgProc = GeDlgProcMultiple; } else { if (pEinfo->fRouter) { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_RouterGeneralSingle ); } else { ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_GeneralSingle ); } ppage->pfnDlgProc = GeDlgProcSingle; } } else { ASSERT( pEinfo->pEntry->dwType == RASET_Direct ); ppage->pszTemplate = MAKEINTRESOURCE( PID_GE_GeneralDirect ); ppage->pfnDlgProc = GeDlgProc; } ppage->lParam = (LPARAM )pEinfo; // Options page. // ppage = &apage[ PE_OePage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (pEinfo->fRouter) ? MAKEINTRESOURCE( PID_OE_OptionsRouter ) : ((pEinfo->pEntry->dwType == RASET_Phone) ? MAKEINTRESOURCE( PID_OE_Options ) : MAKEINTRESOURCE( PID_OE_OptionsVD )); ppage->pfnDlgProc = OeDlgProc; // Security page. // ppage = &apage[ PE_LoPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; // //Add new Security Page for bug 193987 PSK // if ( pEinfo->pEntry->dwType == RASET_Vpn ) { ppage->pszTemplate = MAKEINTRESOURCE( PID_LO_SecurityVpn ); } else { ppage->pszTemplate = MAKEINTRESOURCE( PID_LO_Security ); } ppage->pfnDlgProc = LoDlgProc; // Network page. // ppage = &apage[ PE_NePage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = MAKEINTRESOURCE( PID_NE_Network ); ppage->pfnDlgProc = NeDlgProc; // Advanced page. // (AboladeG) The page is shown if the user is admin and // there is at least one LAN connection, or if this phonebook entry // is already shared. // nPageIndex = PE_SaPage; if((!pEinfo->fIsUserAdminOrPowerUser) || (pEinfo->fRouter)) { --nPages; } else { HRESULT hr; BOOL fShowAdvancedUi = TRUE; INetConnectionUiUtilities* pncuu = NULL; // Check if ZAW is denying access to the Shared Access UI // hr = HrCreateNetConnectionUtilities(&pncuu); if (SUCCEEDED(hr)) { if(FALSE == INetConnectionUiUtilities_UserHasPermission(pncuu, NCPERM_ShowSharedAccessUi) && FALSE == INetConnectionUiUtilities_UserHasPermission(pncuu, NCPERM_PersonalFirewallConfig)) fShowAdvancedUi = FALSE; INetConnectionUiUtilities_Release(pncuu); } if (!fShowAdvancedUi) { --nPages; } else { // Finally, check whether TCP/IP is installed or not. // if (!FIsTcpipInstalled()) { --nPages; } else { ppage = &apage[ nPageIndex++ ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; { PROPSHEETPAGEW psp; hr = HrLoadHNetGetFirewallSettingsPage (&psp, pEinfo); if (hr == S_OK) *ppage = psp; } if (hr != S_OK) { ppage->pszTemplate = MAKEINTRESOURCE( PID_SA_HomenetUnavailable ); ppage->pfnDlgProc = SaUnavailDlgProc; } } } } if (pEinfo->pApiArgs->dwFlags & RASEDFLAG_ShellOwned) { INT i; BOOL fStatus; RASEDSHELLOWNEDR2* pShellOwnedInfo; pShellOwnedInfo = (RASEDSHELLOWNEDR2*)pEinfo->pApiArgs->reserved2; // The property sheet is to be invoked by the shell, using the shell // convention of adding pages via callback. // for (i = 0; i < nPages; ++i) { HPROPSHEETPAGE h; h = CreatePropertySheetPage( &apage[ i ] ); if (!h) { TRACE( "CreatePage failed" ); break; } fStatus = pShellOwnedInfo->pfnAddPage( h, pShellOwnedInfo->lparam ); if (!fStatus) { TRACE( "AddPage failed" ); DestroyPropertySheetPage( h ); break; } } if (i < nPages) { ErrorDlg( pEinfo->pApiArgs->hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); } } else { PROPSHEETHEADER header; PWSTR pszBuf = NULL; PWSTR pszHeader; DWORD cb; HICON hIcon = NULL; DWORD dwDisplayIcon = 0; int i; HPROPSHEETPAGE hPages[PE_PageCount]; //For whistler bug 382720 349866 gangz //to fusionalize well for both rasdlg pages in NCW and //property pages launched by pressing "Property" button //besides following the normal fusion steps: we have to // (1) add _WIN32_WINNT=0x501 in the file sources // (2) use the phpage member in PROPSHEETHEADER structure, that is // use CreatePropertySheetPage() to create page handles for (i = 0; i < nPages; ++i) { hPages[i] = CreatePropertySheetPage( &apage[ i ] ); if ( !hPages[i] ) { TRACE( "CreatePage failed" ); break; } } if (i < nPages) { ErrorDlg( pEinfo->pApiArgs->hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); } else { // Create the correct properties header pszHeader = PszFromId(g_hinstDll, SID_PropertiesHeader); if (pszHeader) { cb = lstrlenW(pEinfo->pEntry->pszEntryName) + 1 + lstrlenW(pszHeader) + 1; pszBuf = Malloc(cb * sizeof(TCHAR)); if (!pszBuf) { TRACE("Properties header allocation failed"); } else { lstrcpyW(pszBuf, pEinfo->pEntry->pszEntryName); lstrcatW(pszBuf, L" "); lstrcatW(pszBuf, pszHeader); } Free(pszHeader); } //For whistler bug 372078 364876 gangz // hIcon = GetCurrentIconEntryType(pEinfo->pEntry->dwType, TRUE); //TRUE means small Icon if (hIcon) { dwDisplayIcon = PSH_USEHICON; } // The property sheet is to be invoked directly. // ZeroMemory( &header, sizeof(header) ); header.dwSize = sizeof(PROPSHEETHEADER); // header.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_USECALLBACK | dwDisplayIcon; header.dwFlags = PSH_NOAPPLYNOW | PSH_USECALLBACK | dwDisplayIcon; header.hwndParent = pEinfo->pApiArgs->hwndOwner; header.hInstance = g_hinstDll; header.pszCaption = (pszBuf)?(pszBuf):(pEinfo->pEntry->pszEntryName); header.nPages = nPages; // header.ppsp = apage; header.phpage = hPages; header.hIcon = hIcon; header.pfnCallback = UnHelpCallbackFunc; if (PropertySheet( &header ) == -1) { TRACE( "PropertySheet failed" ); ErrorDlg( pEinfo->pApiArgs->hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); } Free0(pszBuf); //For whistler bug 372078 //GetCurrentIconEntryType() loads Icon from netshell where the icon is loaded //by LoadImage() without LR_SHARED, so I have to destroy it when we are done //with it // if (hIcon) { DestroyIcon( hIcon ); } } } } //---------------------------------------------------------------------------- // 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; TRACE( "PeApply" ); pInfo = PeContext( hwndPage ); ASSERT( pInfo ); if (pInfo == NULL) { return ERROR_CAN_NOT_COMPLETE; } pEntry = pInfo->pArgs->pEntry; ASSERT( pEntry ); // Save General page fields. // ASSERT( pInfo->hwndGe ); { DTLNODE* pNode; // Retrieve the lone common control. // pEntry->fShowMonitorIconInTaskBar = Button_GetCheck( pInfo->hwndCbShowIcon ); if (pEntry->dwType == RASET_Phone) { DWORD dwCount; dwCount = GeSaveLvDeviceChecks( pInfo ); // Don't allow the user to deselect all of the // devices if ( (pInfo->pArgs->fMultipleDevices) && (dwCount == 0) ) { MsgDlg( hwndPage, SID_SelectDevice, NULL ); PropSheet_SetCurSel ( pInfo->hwndDlg, pInfo->hwndGe, 0 ); SetFocus ( pInfo->hwndLvDevices ); return FALSE; } // Save the "shared phone number" setting. As usual, single // device mode implies shared mode, allowing things to fall // through correctly. // if (pInfo->pArgs->fMultipleDevices) { pEntry->fSharedPhoneNumbers = Button_GetCheck( pInfo->hwndCbSharedPhoneNumbers ); } else { pEntry->fSharedPhoneNumbers = TRUE; } // Set the phone number set for the first phone number of the // current link (shared or selected) to the contents of the phone // number controls. // GeGetPhoneFields( pInfo, pInfo->pCurLinkNode ); // Swap lists, saving updates to caller's global list of area // codes. Caller's original list will be destroyed by PeTerm. // if (pInfo->pListAreaCodes) { DtlSwapLists( pInfo->pArgs->pUser->pdtllistAreaCodes, pInfo->pListAreaCodes ); pInfo->pArgs->pUser->fDirty = TRUE; } } else if (pEntry->dwType == RASET_Vpn) { // For whistler 522872 DTLNODE* pNodeTmp = NULL; PBLINK* pLink = NULL; PBPHONE* pPhone = NULL; // Save host name, i.e. the VPN phone number. // pNodeTmp = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNodeTmp ); pLink = (PBLINK* )DtlGetData( pNodeTmp ); pNodeTmp = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if(NULL == pNodeTmp) { return FALSE; } pPhone = (PBPHONE* )DtlGetData( pNodeTmp ); Free0( pPhone->pszPhoneNumber ); pPhone->pszPhoneNumber = GetText( pInfo->hwndEbHostName ); FirstPhoneNodeToPhoneList( pLink->pdtllistPhones, pNodeTmp ); // Any prequisite entry selection change has been saved already. // Just need to toss it if disabled. // if (!Button_GetCheck( pInfo->hwndCbDialAnotherFirst )) { Free0( pEntry->pszPrerequisiteEntry ); pEntry->pszPrerequisiteEntry = NULL; Free0( pEntry->pszPrerequisitePbk ); pEntry->pszPrerequisitePbk = NULL; } } else if (pEntry->dwType == RASET_Broadband) { DTLNODE* pNodeTmp = NULL; PBLINK* pLink = NULL; PBPHONE* pPhone = NULL; // Save service name, i.e. the broadband phone number. // pNodeTmp = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNodeTmp ); pLink = (PBLINK* )DtlGetData( pNodeTmp ); pNodeTmp = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if(NULL == pNodeTmp) { return FALSE; } pPhone = (PBPHONE* )DtlGetData( pNodeTmp ); Free0( pPhone->pszPhoneNumber ); pPhone->pszPhoneNumber = GetText( pInfo->hwndEbBroadbandService ); FirstPhoneNodeToPhoneList( pLink->pdtllistPhones, pNodeTmp ); } else if (pEntry->dwType == RASET_Direct) { DTLNODE* pNodeTmp = NULL; PBLINK* pLink = NULL; // The currently enabled device is the one // that should be used for the connection. Only // one device will be enabled (DnUpdateSelectedDevice). for (pNodeTmp = DtlGetFirstNode( pEntry->pdtllistLinks ); pNodeTmp; pNodeTmp = DtlGetNextNode( pNodeTmp )) { pLink = (PBLINK* )DtlGetData( pNodeTmp ); ASSERT(pLink); if ( pLink->fEnabled ) break; } // If we found a link successfully, deal with it // now. if ( pLink && pLink->fEnabled ) { if (pLink->pbport.pbdevicetype == PBDT_ComPort) MdmInstallNullModem (pLink->pbport.pszPort); } } } // Save Options page fields. // if (pInfo->hwndOe) { UINT unValue; BOOL f; INT iSel; pEntry->fShowDialingProgress = Button_GetCheck( pInfo->hwndCbDisplayProgress ); // Note: The'fPreviewUserPw', 'fPreviewDomain' fields are updated as // they are changed. pEntry->fPreviewPhoneNumber = Button_GetCheck( pInfo->hwndCbPreviewNumber ); unValue = GetDlgItemInt( pInfo->hwndOe, CID_OE_EB_RedialAttempts, &f, FALSE ); if (f && unValue <= RAS_MaxRedialCount) { pEntry->dwRedialAttempts = unValue; } iSel = ComboBox_GetCurSel( pInfo->hwndLbRedialTimes ); pEntry->dwRedialSeconds = (DWORD )ComboBox_GetItemData( pInfo->hwndLbRedialTimes, iSel ); iSel = ComboBox_GetCurSel( pInfo->hwndLbIdleTimes ); pEntry->lIdleDisconnectSeconds = (LONG )ComboBox_GetItemData( pInfo->hwndLbIdleTimes, iSel ); if (pInfo->pArgs->fRouter) { pEntry->fRedialOnLinkFailure = Button_GetCheck( pInfo->hwndRbPersistent ); } else { pEntry->fRedialOnLinkFailure = Button_GetCheck( pInfo->hwndCbRedialOnDrop ); } // Note: dwDialMode is saved as changed. // Note: X.25 settings are saved at OK on that dialog. } // Save Security page fields. // if (pInfo->hwndLo) { if (Button_GetCheck( pInfo->hwndRbTypicalSecurity )) { LoSaveTypicalAuthSettings( pInfo ); if (pEntry->dwTypicalAuth == TA_CardOrCert) { /* // Toss any existing advanced EAP configuration remnants when // typical smartcard, per bug 262702 and VBaliga email. // Free0( pEntry->pCustomAuthData ); pEntry->pCustomAuthData = NULL; pEntry->cbCustomAuthData = 0; */ (void) DwSetCustomAuthData( pEntry, 0, NULL); TRACE( "RasSetEapUserData" ); ASSERT( g_pRasSetEapUserData ); g_pRasSetEapUserData( INVALID_HANDLE_VALUE, pInfo->pArgs->pFile->pszPath, pEntry->pszEntryName, NULL, 0 ); TRACE( "RasSetEapUserData done" ); } } if (pEntry->dwType == RASET_Phone) { Free0( pEntry->pszScriptAfter ); SuGetInfo( &pInfo->suinfo, &pEntry->fScriptAfter, &pEntry->fScriptAfterTerminal, &pEntry->pszScriptAfter ); } } // Save Network page fields. // We won't have anything to do if we never initialized pNetCfg. // if (pInfo->pNetCfg) { HRESULT hr; // Update the phone book entry with the enabled state of the components. // Do this by enumerating the components from the list view item data // and consulting the check state for each. // NeSaveBindingChanges(pInfo); hr = INetCfg_Apply (pInfo->pNetCfg); if (((NETCFG_S_REBOOT == hr) || (pInfo->fRebootAlreadyRequested)) && pInfo->pNetConUtilities) { DWORD dwFlags = QUFR_REBOOT; if (!pInfo->fRebootAlreadyRequested) dwFlags |= QUFR_PROMPT; //$TODO NULL caption? INetConnectionUiUtilities_QueryUserForReboot ( pInfo->pNetConUtilities, pInfo->hwndDlg, NULL, dwFlags); } } #if 0 //!!! 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; } #endif // 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); 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. Commit the changes to the phonebook // and preferences. This occurs immediately in "ShellOwned" mode where // the RasEntryDlg API has already returned, but is otherwise deferred // until the API is ready to return. // if (pInfo->pArgs->pApiArgs->dwFlags & RASEDFLAG_ShellOwned) { EuCommit( pInfo->pArgs ); } else { pInfo->pArgs->fCommit = TRUE; } return TRUE; } 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" ); // In "ShellOwned" mode where the RasEntryDlg API has already returned, // output arguments are not recorded. // if (!(pInfo->pArgs->pApiArgs->dwFlags & RASEDFLAG_ShellOwned)) { pInfo->pArgs->pApiArgs->dwError = dwError; } PropSheet_PressButton( pInfo->hwndDlg, PSBTN_CANCEL ); } VOID PeExitInit( IN HWND hwndDlg, IN EINFO* pEinfo, IN DWORD dwError ) // Utility to report errors within PeInit and other first page // initialization. 'HwndDlg' is the dialog window. 'PEinfo' is the // common context block, i.e. the PropertySheet argument. 'DwError' is // the error that occurred. // { // In "ShellOwned" mode where the RasEntryDlg API has already returned, // output arguments are not recorded. // if (!(pEinfo->pApiArgs->dwFlags & RASEDFLAG_ShellOwned)) { pEinfo->pApiArgs->dwError = dwError; } 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; TRACE( "PeInit" ); hwndDlg = GetParent( hwndFirstPage ); // 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 ); PeExitInit( hwndDlg, pArgs, ERROR_NOT_ENOUGH_MEMORY ); return NULL; } ZeroMemory( pInfo, sizeof(PEINFO) ); pInfo->pArgs = pArgs; pInfo->hwndDlg = hwndDlg; pInfo->hwndFirstPage = hwndFirstPage; if (!SetProp( hwndDlg, g_contextId, pInfo )) { TRACE(" Context NOT set" ); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); Free( pInfo ); PeExitInit( hwndDlg, pArgs, ERROR_UNKNOWN ); return NULL; } TRACE( "Context set" ); } // Position the dialog per API caller's instructions. // //For whislter bug 238459, we center the Property dialog box on its //parent window rather than shift it as before. gangz // PositionDlg( hwndDlg, 0, pArgs->pApiArgs->xDlg, pArgs->pApiArgs->yDlg ); // Mess with the title bar gadgets. // //TweakTitleBar( hwndDlg ); // Indicate no device has yet been selected. // pInfo->iDeviceSelected = -1; // Indicate the "no security settings for SLIP" popup is appropriate for // the entry and has not been viewed yet during this visit. // if (pArgs->pEntry->dwBaseProtocol == BP_Slip) { pInfo->fShowSlipPopup = TRUE; } // Initialize COM which may be needed by netshell calls. // { HRESULT hr; hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if (hr == RPC_E_CHANGED_MODE) { hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); } if (hr == S_OK || hr == S_FALSE) { pInfo->fComInitialized = TRUE; } } #if 0 // Set even fixed tab widths. // SetEvenTabWidths( hwndDlg, PE_PageCount ); #endif 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->pArgs->pApiArgs->dwFlags & RASEDFLAG_ShellOwned) { EuFree(pInfo->pArgs); pInfo->pArgs = NULL; } if (pInfo->hwndLbDialAnotherFirst) { GeClearLbDialAnotherFirst( pInfo->hwndLbDialAnotherFirst ); } if (pInfo->pListAreaCodes) { DtlDestroyList( pInfo->pListAreaCodes, DestroyPszNode ); } #if 0 if (pInfo->pListEapcfgs) { DtlDestroyList( pInfo->pListEapcfgs, DestroyEapcfgNode ); } #endif if (pInfo->fCuInfoInitialized) { CuFree( &pInfo->cuinfo ); } if (pInfo->fSuInfoInitialized) { SuFree( &pInfo->suinfo ); } // Cleanup networking page context. // { // Release our UI info callback object after revoking its info. // if (pInfo->punkUiInfoCallback) { RevokePeinfoFromUiInfoCallbackObject (pInfo->punkUiInfoCallback); ReleaseObj (pInfo->punkUiInfoCallback); } //!!! Major hack: Get the list view on the networking page // to dump its items before the pInfo and pInfo->pNetCfg go away. // We have to do this here when we dismiss the property sheet // from the General tab. When this happens, the general page // is destroyed first (causing us to wind up here in PeTerm) // before the networking page is destroyed. When the networking // page is destroyed, its listview will also get destroyed // causing all of its items to be deleted. If those LVN_ITEMDELETED // notifications show up after pInfo and pInfo->pNetCfg are long // gone, badness ensues. We need to solve this by decoupling // PeTerm from a WM_DESTROY message and hooking it up to some // later notification (like a page callback). // ListView_DeleteAllItems (pInfo->hwndLvComponents); if (pInfo->pNetConUtilities) { INetConnectionUiUtilities_Release(pInfo->pNetConUtilities); } if (pInfo->pNetCfg) { HrUninitializeAndReleaseINetCfg (pInfo->fInitCom, pInfo->pNetCfg, pInfo->fNetCfgLock); } SetupDiDestroyClassImageList (&pInfo->cild); } if (pInfo->fComInitialized) { CoUninitialize(); } Free( pInfo ); TRACE("Context freed"); } RemoveProp( GetParent( hwndPage ), g_contextId ); } //---------------------------------------------------------------------------- // General property page (non-VPN) // Listed alphabetically following dialog proc //---------------------------------------------------------------------------- INT_PTR CALLBACK GeDlgProcSingle( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the General page of the Entry Property sheet // when in single device mode. Parameters and return value are as // described for standard windows 'DialogProc's. // { #if 0 TRACE4( "GeDlgProcS(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif if (ListView_OwnerHandler( hwnd, unMsg, wparam, lparam, GeLvDevicesCallbackSingle )) { return TRUE; } return GeDlgProc( hwnd, unMsg, wparam, lparam ); } INT_PTR CALLBACK GeDlgProcMultiple( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the General page of the Entry Property sheet // when in multiple device mode. Parameters and return value are as // described for standard windows 'DialogProc's. // { #if 0 TRACE4( "GeDlgProcS(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif if (ListView_OwnerHandler( hwnd, unMsg, wparam, lparam, GeLvDevicesCallbackMultiple )) { return TRUE; } return GeDlgProc( hwnd, unMsg, wparam, lparam ); } INT_PTR CALLBACK GeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the General page of the Entry Property sheet. // Called directly for VPNs or called by one of the two non-VPN stubs so // 'pInfo' lookup is not required for every messages. Parameters and // return value are as described for standard windows 'DialogProc's. // { switch (unMsg) { case WM_INITDIALOG: { return GeInit( hwnd, (EINFO* )(((PROPSHEETPAGE* )lparam)->lParam) ); } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwGeHelp, hwnd, unMsg, wparam, lparam ); break; } case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case PSN_APPLY: { BOOL fValid; TRACE( "GeAPPLY" ); fValid = PeApply( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, (fValid) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ); return TRUE; } case PSN_RESET: { TRACE( "GeRESET" ); SetWindowLong( hwnd, DWLP_MSGRESULT, FALSE ); break; } case LVXN_SETCHECK: { PEINFO* pInfo; // An item was just checked or unchecked. // pInfo = PeContext( hwnd ); ASSERT( pInfo ); if (pInfo == NULL) { break; } GeUpdatePhoneNumberFields( pInfo, FALSE ); // For whistler bug 29419 gangz // We should grey out the "All device call the same number" // if not all the modems are selected // do { int i, iCount = 0, iChecked = 0; BOOL fEnable = TRUE; iCount = ListView_GetItemCount( pInfo->hwndLvDevices ); if ( iCount <= 0 ) { break; } for ( i = 0; i < iCount; i ++ ) { if ( ListView_GetCheck( pInfo->hwndLvDevices, i) ) { iChecked ++; } if ( 2 <=iChecked ) { break; } } if ( iChecked < 2 ) { fEnable = FALSE; } if ( pInfo->hwndCbSharedPhoneNumbers ) { EnableWindow( pInfo->hwndCbSharedPhoneNumbers, fEnable); } }while(FALSE); break; } case LVN_ITEMCHANGED: { NM_LISTVIEW* p; p = (NM_LISTVIEW* )lparam; if ((p->uNewState & LVIS_SELECTED) && !(p->uOldState & LVIS_SELECTED)) { PEINFO* pInfo; // This item was just selected. // pInfo = PeContext( hwnd ); ASSERT( pInfo ); if (pInfo == NULL) { break; } GeUpdatePhoneNumberFields( pInfo, FALSE ); GeUpdateUpDownButtons( pInfo ); } break; } } break; } case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } return GeCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } case WM_DESTROY: { PeTerm( hwnd ); break; } } return FALSE; } VOID GeAlternates( IN PEINFO* pInfo ) // Called when the "Alternates" button is pressed to popup the alternate // phone number dialog. // { // Pick up any control window changes into the underlying link so the // dialog will reflect them. // GeGetPhoneFields( pInfo, pInfo->pCurLinkNode ); if (pInfo->pArgs->fRouter) { PBLINK* pLink; DTLLIST* pListPsz; DTLNODE* pNode; // TAPI modifiers are not offered in the demand dial connection case, // where user enters only a simple string phone number. The old // NT4-style Alternates dialog that allows simple string edits only is // used here. First, must convert the NT5-style list of PBPHONE nodes // to a list of PSZ nodes that the old dialog expects. // pListPsz = DtlCreateList( 0L ); if (!pListPsz) { return; } pLink = (PBLINK* )DtlGetData( pInfo->pCurLinkNode ); for (pNode = DtlGetFirstNode( pLink->pdtllistPhones ); pNode; pNode = DtlGetNextNode( pNode ) ) { PBPHONE* pPhone; DTLNODE* pNodePsz; pPhone = (PBPHONE* )DtlGetData( pNode ); ASSERT( pPhone ); if (pPhone->pszPhoneNumber && *(pPhone->pszPhoneNumber)) { pNodePsz = CreatePszNode( pPhone->pszPhoneNumber ); if (pNodePsz) { DtlAddNodeLast( pListPsz, pNodePsz ); } } } // Call the old-sytle Alternates dialog which is shared with the // demand dial wizard. // if (PhoneNumberDlg( pInfo->hwndGe, TRUE, pListPsz, &pLink->fPromoteAlternates )) { // User pressed OK. Convert back to a PBPHONE node list. // while (pNode = DtlGetFirstNode( pLink->pdtllistPhones )) { DtlRemoveNode( pLink->pdtllistPhones, pNode ); DestroyPhoneNode( pNode ); } for (pNode = DtlGetFirstNode( pListPsz ); pNode; pNode = DtlGetNextNode( pNode ) ) { TCHAR* psz; DTLNODE* pPhoneNode; PBPHONE* pPhone; psz = (TCHAR* )DtlGetData( pNode ); if (!psz) { continue; } pPhoneNode = CreatePhoneNode(); if (!pPhoneNode) { continue; } pPhone = (PBPHONE* )DtlGetData( pPhoneNode ); if (!pPhone) { continue; } pPhone->pszPhoneNumber = psz; DtlPutData( pNode, NULL ); DtlAddNodeLast( pLink->pdtllistPhones, pPhoneNode ); } // Refresh the displayed phone number information, since user's // edits in the dialog may have changed them. // GeSetPhoneFields( pInfo, pInfo->pCurLinkNode, FALSE ); } DtlDestroyList( pListPsz, DestroyPszNode ); } else { // Popup the Alternate Phone Number dialog on the link. // if (AlternatePhoneNumbersDlg( pInfo->hwndDlg, pInfo->pCurLinkNode, pInfo->pListAreaCodes )) { // User pressed OK. Refresh the displayed phone number // information, since user's edits in the dialog may have changed // them. // GeSetPhoneFields( pInfo, pInfo->pCurLinkNode, FALSE ); } } } VOID GeDialingRules( IN PEINFO* pInfo ) // Called when the "Rules" button is pressed to popup the tapi // dialing rules dialog. // { TCHAR pszAreaCode[RAS_MaxPhoneNumber]; TCHAR pszPhoneNumber[RAS_MaxPhoneNumber]; DWORD dwErr, dwCountryCode, dwLineId; COUNTRY* pCountry = NULL; INT iSel; TRACE( "GeDialingRules" ); // Get the current phone number // GetWindowText ( pInfo->hwndEbPhoneNumber, pszPhoneNumber, sizeof(pszPhoneNumber) / sizeof(TCHAR) ); // Get the current area code // GetWindowText ( pInfo->hwndClbAreaCodes, pszAreaCode, sizeof(pszAreaCode) / sizeof(TCHAR) ); // Get the current country code // iSel = ComboBox_GetCurSel ( pInfo->hwndLbCountryCodes ); if (iSel >= 0) { pCountry = (COUNTRY*) ComboBox_GetItemDataPtr ( pInfo->hwndLbCountryCodes, iSel ); } dwCountryCode = (pCountry) ? pCountry->dwCode : 0; // Popup TAPI dialing rules dialog. // dwErr = TapiLocationDlg( g_hinstDll, &(pInfo->cuinfo.hlineapp), pInfo->hwndDlg, dwCountryCode, pszAreaCode, pszPhoneNumber, 0 ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadTapiInfo, dwErr, NULL ); } } VOID GeClearLbDialAnotherFirst( IN HWND hwndLbDialAnotherFirst ) // Clear prerequisite entry list box. 'hwndLbDialAnotherFirst' is the // window handle of the listbox control. context. // { PREREQITEM* pItem; while (pItem = ComboBox_GetItemDataPtr( hwndLbDialAnotherFirst, 0 )) { ComboBox_DeleteString( hwndLbDialAnotherFirst, 0 ); Free0( pItem->pszEntry ); Free0( pItem->pszPbk ); Free( pItem ); } } BOOL GeCommand( 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. // { TRACE3( "GeCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl ); switch (wId) { case CID_GE_PB_MoveUp: { GeMoveDevice( pInfo, TRUE ); return TRUE; } case CID_GE_PB_MoveDown: { GeMoveDevice( pInfo, FALSE ); return TRUE; } case CID_GE_PB_Configure: { GeConfigure( pInfo ); return TRUE; } case CID_GE_PB_Alternates: { GeAlternates( pInfo ); return TRUE; } case CID_GE_PB_DialingRules: { GeDialingRules( pInfo ); return TRUE; } case CID_GE_CB_SharedPhoneNumber: { GeUpdatePhoneNumberFields( pInfo, TRUE ); return TRUE; } case CID_GE_CB_UseDialingRules: { if (CuDialingRulesCbHandler( &pInfo->cuinfo, wNotification )) { return TRUE; } break; } case CID_GE_LB_CountryCodes: { if (CuCountryCodeLbHandler( &pInfo->cuinfo, wNotification )) { return TRUE; } break; } case CID_GE_CB_DialAnotherFirst: { GeUpdateDialAnotherFirstState( pInfo ); return TRUE; } case CID_GE_LB_DialAnotherFirst: { if (wNotification == CBN_SELCHANGE) { GeDialAnotherFirstSelChange( pInfo ); return TRUE; } break; } case CID_GE_LB_Devices: { if (wNotification == CBN_SELCHANGE) { DTLLIST* pList; DTLNODE* pNode, *pNode2; PBLINK * pLink; pList = pInfo->pArgs->pEntry->pdtllistLinks; // Get node from current selection pNode = (DTLNODE* )ComboBox_GetItemDataPtr( pInfo->hwndLbDevices, ComboBox_GetCurSel( pInfo->hwndLbDevices ) ); if(NULL == pNode) { break; } // Remove selected item from list of links // and disable all other links DtlRemoveNode ( pList, pNode ); for (pNode2 = DtlGetFirstNode (pList); pNode2; pNode2 = DtlGetNextNode (pNode2)) { pLink = (PBLINK* )DtlGetData( pNode2 ); pLink->fEnabled = FALSE; } // Enable selected device and Re-add // in list of links at front pLink = (PBLINK* )DtlGetData( pNode ); pLink->fEnabled = TRUE; DtlAddNodeFirst( pList, pNode ); } break; } } return FALSE; } VOID GeConfigure( IN PEINFO* pInfo ) // Called when the "Configure" button is pressed to popup the appropriate // device configuration dialog. // { DTLNODE* pNode; PBLINK* pLink; PBENTRY* pEntry; BOOL fMultilinking = FALSE; pEntry = pInfo->pArgs->pEntry; // pmay: 245860 // // Need to allow config of null modem speed. // if ( pEntry->dwType == RASET_Direct ) { INT iSel; iSel = ComboBox_GetCurSel( pInfo->hwndLbDevices ); pNode = (DTLNODE*) ComboBox_GetItemDataPtr ( pInfo->hwndLbDevices, iSel ); } else { pNode = (DTLNODE* )ListView_GetSelectedParamPtr( pInfo->hwndLvDevices ); fMultilinking = (ListView_GetCheckedCount( pInfo->hwndLvDevices ) > 1 && pEntry->dwDialMode == RASEDM_DialAll); } if (!pNode) { return; } pLink = (PBLINK* )DtlGetData( pNode ); DeviceConfigureDlg( pInfo->hwndDlg, pLink, pEntry, !fMultilinking, pInfo->pArgs->fRouter); } VOID GeDialAnotherFirstSelChange( IN PEINFO* pInfo ) // Called when the prerequisite entry selection changes. 'PInfo' is the // property sheet context. // { PBENTRY* pEntry; PREREQITEM* pItem; INT iSel; iSel = ComboBox_GetCurSel( pInfo->hwndLbDialAnotherFirst ); if (iSel < 0) { return; } pEntry = pInfo->pArgs->pEntry; Free0( pEntry->pszPrerequisiteEntry ); Free0( pEntry->pszPrerequisitePbk ); pItem = (PREREQITEM* ) ComboBox_GetItemDataPtr( pInfo->hwndLbDialAnotherFirst, iSel ); if(NULL != pItem) { pEntry->pszPrerequisiteEntry = StrDup( pItem->pszEntry ); pEntry->pszPrerequisitePbk = StrDup( pItem->pszPbk ); } pEntry->fDirty = TRUE; } BOOL GeFillLbDialAnotherFirst( IN PEINFO* pInfo, IN BOOL fAbortIfPrereqNotFound ) // Fill prerequisite entry list box with all non-VPN entries in the // phonebook, and select the prerequiste one. 'PInfo' is the property // sheet context. 'FAbortIfPrereqNotFound' means the list should not be // filled unless the entry's prerequisite entry is found and selected. // // Returns TRUE if a selection was made, FALSE otherwise. // { DWORD i; INT iThis; INT iSel; TCHAR* pszEntry; TCHAR* pszPrerequisiteEntry = NULL; RASENTRYNAME* pRens; RASENTRYNAME* pRen; DWORD dwRens; GeClearLbDialAnotherFirst( pInfo->hwndLbDialAnotherFirst ); iSel = -1; pszEntry = pInfo->pArgs->pEntry->pszEntryName; // // Make a dup of this prerequisite entry here. Otherwise // this leads to accessing freed memory when _SetCurSelNotify // frees pszPrerequisiteEntry - [raos]. // if(NULL != pInfo->pArgs->pEntry->pszPrerequisiteEntry) { pszPrerequisiteEntry = StrDup( pInfo->pArgs->pEntry->pszPrerequisiteEntry); } if (GetRasEntrynameTable( &pRens, &dwRens ) != 0) { return FALSE; } for (i = 0, pRen = pRens; i < dwRens; ++i, ++pRen ) { PREREQITEM* pItem; if (lstrcmp( pRen->szEntryName, pszEntry ) == 0) { continue; } pItem = Malloc( sizeof(PREREQITEM) ); if (!pItem) { continue; } pItem->pszEntry = StrDup( pRen->szEntryName ); pItem->pszPbk = StrDup( pRen->szPhonebookPath ); if (!pItem->pszEntry || !pItem->pszPbk) { Free0( pItem->pszEntry ); Free( pItem ); continue; } iThis = ComboBox_AddItem( pInfo->hwndLbDialAnotherFirst, pItem->pszEntry, pItem ); if (pszPrerequisiteEntry && *(pszPrerequisiteEntry) && lstrcmp( pItem->pszEntry, pszPrerequisiteEntry ) == 0) { iSel = iThis; ComboBox_SetCurSelNotify( pInfo->hwndLbDialAnotherFirst, iSel ); } } Free( pRens ); if (iSel < 0) { if (fAbortIfPrereqNotFound) { GeClearLbDialAnotherFirst( pInfo->hwndLbDialAnotherFirst ); } else { iSel = 0; ComboBox_SetCurSelNotify( pInfo->hwndLbDialAnotherFirst, iSel ); } } Free0(pszPrerequisiteEntry); return (iSel >= 0); } VOID GeFillLbDevices( IN PEINFO* pInfo ) // Populate the already initialized ListBox of devices, selecting the // currently selected item or if none, the first item. 'PInfo' is the // property sheet context. // { DTLNODE* pNode; DTLNODE* pSelNode; DTLLIST* pListLinks; INT iItem; INT iSelItem; TRACE( "GeFillLbDevices" ); pSelNode = NULL; iSelItem = -1; // (Re-)populate the list. // pListLinks = pInfo->pArgs->pEntry->pdtllistLinks; for (pNode = DtlGetFirstNode( pListLinks ), iItem = 0; pNode; pNode = DtlGetNextNode( pNode ), ++iItem) { PBLINK* pLink; DWORD dwImage; TCHAR* pszText; pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); pszText = DisplayPszFromPpbport( &pLink->pbport, &dwImage ); if (pszText) { iItem = ComboBox_AddString( pInfo->hwndLbDevices, pszText ); ComboBox_SetItemData ( pInfo->hwndLbDevices, iItem, pNode ); Free (pszText); } } ComboBox_SetCurSelNotify( pInfo->hwndLbDevices, 0 ); } VOID GeFillLvDevices( IN PEINFO* pInfo ) // Populate the already initialized ListView of devices, selecting the // currently selected item or if none, the first item. 'PInfo' is the // property sheet context. // { DTLNODE* pNode; DTLNODE* pSelNode; DTLLIST* pListLinks; INT iItem; INT iSelItem; BOOL bFirstTime = TRUE; INT cItems; TRACE( "GeFillLvDevices" ); pSelNode = NULL; iSelItem = -1; if (ListView_GetItemCount( pInfo->hwndLvDevices ) > 0) { // ListView has been filled. Lookup the selected link node, if any, // then save the check state to the links, and delete all items from // the list. // if (pInfo->iDeviceSelected >= 0) { pSelNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, pInfo->iDeviceSelected ); } GeSaveLvDeviceChecks( pInfo ); ListView_DeleteAllItems( pInfo->hwndLvDevices ); bFirstTime = FALSE; } // (Re-)populate the list. // pListLinks = pInfo->pArgs->pEntry->pdtllistLinks; for (pNode = DtlGetFirstNode( pListLinks ), iItem = 0; pNode; pNode = DtlGetNextNode( pNode ), ++iItem) { PBLINK* pLink; DWORD dwImage; TCHAR* pszText; pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); pszText = DisplayPszFromPpbport( &pLink->pbport, &dwImage ); if (pszText) { LV_ITEM item; ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iItem = iItem; item.lParam = (LPARAM )pNode; item.pszText = pszText; item.cchTextMax = wcslen(pszText) + 1; item.iImage = dwImage; iItem = ListView_InsertItem( pInfo->hwndLvDevices, &item ); Free( pszText ); if (pNode == pSelNode) { iSelItem = iItem; pInfo->iDeviceSelected = iItem; } /* if (pInfo->pArgs->fMultipleDevices) { ListView_SetCheck( pInfo->hwndLvDevices, iItem, pLink->fEnabled ); } */ } } if(pInfo->pArgs->fMultipleDevices) { INT i = -1; while ((i = ListView_GetNextItem( pInfo->hwndLvDevices, i, LVNI_ALL )) >= 0) { DTLNODE* pNodeTmp = NULL; PBLINK* pLink = NULL; pNodeTmp = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, i ); ASSERT( pNodeTmp ); if(NULL == pNodeTmp) { continue; } pLink = (PBLINK* )DtlGetData( pNodeTmp ); ASSERT( pLink ); ListView_SetCheck( pInfo->hwndLvDevices, i, pLink->fEnabled); } } if (bFirstTime == TRUE) { // Add a single column exactly wide enough to fully display // the widest member of the list. // LV_COLUMN col; ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT; col.fmt = LVCFMT_LEFT; ListView_InsertColumn( pInfo->hwndLvDevices, 0, &col ); ListView_SetColumnWidth( pInfo->hwndLvDevices, 0, LVSCW_AUTOSIZE_USEHEADER ); } // EuInit creates a bogus device if there are none guaranteeing that the // device list is never empty. // ASSERT( iItem > 0 ); // Select the previously selected item, or the first item if none. This // will trigger an update of the phone number related controls. The // "previous selection" index is updated to the new index of the same // item. // if (iSelItem >= 0) { pInfo->iDeviceSelected = iSelItem; } else { iSelItem = 0; } ListView_SetItemState( pInfo->hwndLvDevices, iSelItem, LVIS_SELECTED, LVIS_SELECTED ); } VOID GeInitLvDevices( IN PEINFO* pInfo ) // Initialize the ListView of devices. // { BOOL fChecksInstalled; // Install "listview of checkboxes" handling. // if (pInfo->pArgs->fMultipleDevices) { fChecksInstalled = ListView_InstallChecks( pInfo->hwndLvDevices, g_hinstDll ); if (!fChecksInstalled) return; } // Set the modem, adapter, and other device images. // ListView_SetDeviceImageList( pInfo->hwndLvDevices, g_hinstDll ); // Add a single column exactly wide enough to fully display the widest // member of the list. // ListView_InsertSingleAutoWidthColumn( pInfo->hwndLvDevices ); } VOID GeGetPhoneFields( IN PEINFO* pInfo, OUT DTLNODE* pDstLinkNode ) // Load the phone number group box field settings into the phone number // information of PBLINK node 'pDstLinkNode'. 'PInfo' is the property // sheet context. // { PBLINK* pLink; PBPHONE* pPhone; DTLNODE* pPhoneNode; TRACE( "GeGetPhoneFields" ); pLink = (PBLINK* )DtlGetData( pDstLinkNode ); ASSERT( pLink ); pPhoneNode = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if (pPhoneNode) { CuGetInfo( &pInfo->cuinfo, pPhoneNode ); FirstPhoneNodeToPhoneList( pLink->pdtllistPhones, pPhoneNode ); } } BOOL GeInit( 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( "GeInit" ); // We're first page, so initialize the property sheet. // pInfo = PeInit( hwndPage, pArgs ); if (!pInfo) { return TRUE; } pEntry = pInfo->pArgs->pEntry; // Initialize page-specific context information. // pInfo->hwndGe = hwndPage; // Initialize the "show icon in the taskbar" button, the lone piece of consistency among // the various forms. // //for bug 154607 whistler, Enable/Disable Show Icon on taskbar //check box according to Policy // // { BOOL fShowStatistics = TRUE; NeEnsureNetshellLoaded (pInfo); if ( NULL != pInfo->pNetConUtilities) { fShowStatistics = INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_Statistics); } pInfo->hwndCbShowIcon = GetDlgItem( hwndPage, CID_GE_CB_ShowIcon ); ASSERT( pInfo->hwndCbShowIcon ); if ( pInfo->pArgs->fRouter ) { Button_SetCheck( pInfo->hwndCbShowIcon, FALSE ); ShowWindow( pInfo->hwndCbShowIcon, SW_HIDE ); } else { Button_SetCheck( pInfo->hwndCbShowIcon, pEntry->fShowMonitorIconInTaskBar ); if ( !fShowStatistics ) { EnableWindow( pInfo->hwndCbShowIcon, FALSE ); } } } if (pEntry->dwType == RASET_Vpn) { pInfo->hwndEbHostName = GetDlgItem( hwndPage, CID_GE_EB_HostName ); ASSERT( pInfo->hwndEbHostName ); pInfo->hwndCbDialAnotherFirst = GetDlgItem( hwndPage, CID_GE_CB_DialAnotherFirst ); ASSERT( pInfo->hwndCbDialAnotherFirst ); pInfo->hwndLbDialAnotherFirst = GetDlgItem( hwndPage, CID_GE_LB_DialAnotherFirst ); ASSERT( pInfo->hwndLbDialAnotherFirst ); // Initialize host name, i.e. the "phone number". // { DTLNODE* pNode; PBLINK* pLink; PBPHONE* pPhone; Edit_LimitText( pInfo->hwndEbHostName, RAS_MaxPhoneNumber ); pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNode ); pLink = (PBLINK* )DtlGetData( pNode ); pNode = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if(NULL == pNode) { return TRUE; } pPhone = (PBPHONE* )DtlGetData( pNode ); SetWindowText( pInfo->hwndEbHostName, pPhone->pszPhoneNumber ); DestroyPhoneNode( pNode ); } // Initialize the "dial connected first" controls. // if (pInfo->pArgs->fRouter) { Button_SetCheck( pInfo->hwndCbDialAnotherFirst, FALSE ); EnableWindow( pInfo->hwndCbDialAnotherFirst, FALSE ); ShowWindow( pInfo->hwndCbDialAnotherFirst, SW_HIDE ); EnableWindow( pInfo->hwndLbDialAnotherFirst, FALSE ); ShowWindow(pInfo->hwndLbDialAnotherFirst, SW_HIDE ); ShowWindow( GetDlgItem( hwndPage, CID_GE_GB_FirstConnect ), SW_HIDE ); ShowWindow( GetDlgItem( hwndPage, CID_GE_ST_Explain ), SW_HIDE ); } else { BOOL fEnableLb; fEnableLb = FALSE; if (pEntry->pszPrerequisiteEntry && *(pEntry->pszPrerequisiteEntry)) { if (GeFillLbDialAnotherFirst( pInfo, TRUE )) { fEnableLb = TRUE; } else { // Don't enable the listbox if the prerequisite entry // defined no longer exists. See bug 220420. // Free0( pEntry->pszPrerequisiteEntry ); pEntry->pszPrerequisiteEntry = NULL; Free0( pEntry->pszPrerequisitePbk ); pEntry->pszPrerequisitePbk = NULL; } } Button_SetCheck( pInfo->hwndCbDialAnotherFirst, fEnableLb ); EnableWindow( pInfo->hwndLbDialAnotherFirst, fEnableLb ); if (pArgs->fDisableFirstConnect) { EnableWindow( pInfo->hwndCbDialAnotherFirst, FALSE ); EnableWindow( pInfo->hwndLbDialAnotherFirst, FALSE ); } } return TRUE; } else if (pEntry->dwType == RASET_Broadband) { pInfo->hwndEbBroadbandService = GetDlgItem( hwndPage, CID_GE_EB_ServiceName ); ASSERT( pInfo->hwndEbBroadbandService ); // Initialize host name, i.e. the "phone number". // { DTLNODE* pNode; PBLINK* pLink; PBPHONE* pPhone; Edit_LimitText( pInfo->hwndEbBroadbandService, RAS_MaxPhoneNumber ); pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNode ); pLink = (PBLINK* )DtlGetData( pNode ); pNode = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if(NULL == pNode) { return TRUE; } pPhone = (PBPHONE* )DtlGetData( pNode ); SetWindowText( pInfo->hwndEbBroadbandService, pPhone->pszPhoneNumber ); DestroyPhoneNode( pNode ); } return TRUE; } else if (pEntry->dwType == RASET_Phone) { if (pArgs->fMultipleDevices) { pInfo->hwndLvDevices = GetDlgItem( hwndPage, CID_GE_LV_Devices ); ASSERT( pInfo->hwndLvDevices ); pInfo->hwndPbUp = GetDlgItem( hwndPage, CID_GE_PB_MoveUp ); ASSERT( pInfo->hwndPbUp ); pInfo->hwndPbDown = GetDlgItem( hwndPage, CID_GE_PB_MoveDown ); ASSERT( pInfo->hwndPbDown ); pInfo->hwndCbSharedPhoneNumbers = GetDlgItem( hwndPage, CID_GE_CB_SharedPhoneNumber ); ASSERT( pInfo->hwndCbSharedPhoneNumbers ); } else { // The listview has a different control-ID in single mode so that // a different help context can be provided. // pInfo->hwndLvDevices = GetDlgItem( hwndPage, CID_GE_LV_Device ); ASSERT( pInfo->hwndLvDevices ); } pInfo->hwndPbConfigureDevice = GetDlgItem( hwndPage, CID_GE_PB_Configure ); ASSERT( pInfo->hwndPbConfigureDevice ); if ( pEntry->fGlobalDeviceSettings ) { // Whislter bug 281306. If the entry is set up to use // control panel settings, then hide the option that // allows users to configure the devices per-phonebook. // ShowWindow( pInfo->hwndPbConfigureDevice, SW_HIDE ); } pInfo->hwndStPhoneNumber = GetDlgItem( hwndPage, CID_GE_ST_PhoneNumber ); ASSERT( pInfo->hwndStPhoneNumber ); pInfo->hwndEbPhoneNumber = GetDlgItem( hwndPage, CID_GE_EB_PhoneNumber ); ASSERT( pInfo->hwndEbPhoneNumber ); pInfo->hwndPbAlternates = GetDlgItem( hwndPage, CID_GE_PB_Alternates ); ASSERT( pInfo->hwndPbAlternates ); if (!pInfo->pArgs->fRouter) { pInfo->hwndGbPhoneNumber = GetDlgItem( hwndPage, CID_GE_GB_PhoneNumber ); ASSERT( pInfo->hwndGbPhoneNumber ); pInfo->hwndStAreaCodes = GetDlgItem( hwndPage, CID_GE_ST_AreaCodes ); ASSERT( pInfo->hwndStAreaCodes ); pInfo->hwndClbAreaCodes = GetDlgItem( hwndPage, CID_GE_CLB_AreaCodes ); ASSERT( pInfo->hwndClbAreaCodes ); pInfo->hwndStCountryCodes = GetDlgItem( hwndPage, CID_GE_ST_CountryCodes ); ASSERT( pInfo->hwndStCountryCodes ); pInfo->hwndLbCountryCodes = GetDlgItem( hwndPage, CID_GE_LB_CountryCodes ); ASSERT( pInfo->hwndLbCountryCodes ); pInfo->hwndCbUseDialingRules = GetDlgItem( hwndPage, CID_GE_CB_UseDialingRules ); ASSERT( pInfo->hwndCbUseDialingRules ); pInfo->hwndPbDialingRules = GetDlgItem( hwndPage, CID_GE_PB_DialingRules ); ASSERT( pInfo->hwndPbDialingRules ); } if (pArgs->fMultipleDevices) { // Set the shared phone number checkbox. // Button_SetCheck( pInfo->hwndCbSharedPhoneNumbers, pEntry->fSharedPhoneNumbers ); // Load the icons into the move up and move down buttons. From // what I can tell tell in MSDN, you don't have to close or // destroy the icon handle. // pInfo->hiconUpArr = LoadImage( g_hinstDll, MAKEINTRESOURCE( IID_UpArr ), IMAGE_ICON, 0, 0, 0 ); pInfo->hiconDnArr = LoadImage( g_hinstDll, MAKEINTRESOURCE( IID_DnArr ), IMAGE_ICON, 0, 0, 0 ); pInfo->hiconUpArrDis = LoadImage( g_hinstDll, MAKEINTRESOURCE( IID_UpArrDis ), IMAGE_ICON, 0, 0, 0 ); pInfo->hiconDnArrDis = LoadImage( g_hinstDll, MAKEINTRESOURCE( IID_DnArrDis ), IMAGE_ICON, 0, 0, 0 ); } pInfo->pListAreaCodes = DtlDuplicateList( pInfo->pArgs->pUser->pdtllistAreaCodes, DuplicatePszNode, DestroyPszNode ); CuInit( &pInfo->cuinfo, pInfo->hwndStAreaCodes, pInfo->hwndClbAreaCodes, pInfo->hwndStPhoneNumber, pInfo->hwndEbPhoneNumber, pInfo->hwndStCountryCodes, pInfo->hwndLbCountryCodes, pInfo->hwndCbUseDialingRules, pInfo->hwndPbDialingRules, pInfo->hwndPbAlternates, NULL, NULL, pInfo->pListAreaCodes ); pInfo->fCuInfoInitialized = TRUE; // Configure and populate the device list, selecting the first item. // GeInitLvDevices( pInfo ); GeFillLvDevices( pInfo ); // Set initial focus. // if (pArgs->fMultipleDevices) { SetFocus( pInfo->hwndLvDevices ); } else { ASSERT( IsWindowEnabled( pInfo->hwndEbPhoneNumber ) ); SetFocus( pInfo->hwndEbPhoneNumber ); Edit_SetSel( pInfo->hwndEbPhoneNumber, 0, -1 ); } return FALSE; } else { ASSERT( pEntry->dwType == RASET_Direct ); // The listview has a different control-ID in single mode so that // a different help context can be provided. // pInfo->hwndLbDevices = GetDlgItem( hwndPage, CID_GE_LB_Devices ); ASSERT( pInfo->hwndLbDevices ); // Configure and populate the device list, selecting the first item. // GeFillLbDevices( pInfo ); } return TRUE; } LVXDRAWINFO* GeLvDevicesCallbackMultiple( 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 draw information. // { // Use "full row select" and other recommended options. // // Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'. // static LVXDRAWINFO info = { 1, 0, 0, { 0 } }; return &info; } LVXDRAWINFO* GeLvDevicesCallbackSingle( 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 draw information. // { // Set up to emulate a static text control but with icon on left. // // Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'. // static LVXDRAWINFO info = { 1, 0, LVXDI_DxFill, { LVXDIA_Static } }; return &info; } VOID GeMoveDevice( IN PEINFO* pInfo, IN BOOL fUp ) // Refill the ListView of devices with the selected item moved up or down // one position. 'FUp' is set to move up, otherwise moves down. 'PInfo' // is the property sheeet context. // { DTLNODE* pNode; DTLNODE* pPrevNode; DTLNODE* pNextNode; DTLLIST* pList; if (pInfo->iDeviceSelected < 0) { return; } pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, pInfo->iDeviceSelected ); ASSERT( pNode ); if(NULL == pNode) { return; } pList = pInfo->pArgs->pEntry->pdtllistLinks; if (fUp) { pPrevNode = DtlGetPrevNode( pNode ); if (!pPrevNode) { return; } DtlRemoveNode( pList, pNode ); DtlAddNodeBefore( pList, pPrevNode, pNode ); } else { pNextNode = DtlGetNextNode( pNode ); if (!pNextNode) { return; } DtlRemoveNode( pList, pNode ); DtlAddNodeAfter( pList, pNextNode, pNode ); } GeFillLvDevices( pInfo ); } DWORD GeSaveLvDeviceChecks( IN PEINFO* pInfo ) // Mark links enabled/disabled based on it's check box in the ListView of // devices. Returns the count of enabled devices. // { DWORD dwCount = 0; if (pInfo->pArgs->fMultipleDevices) { INT i; i = -1; while ((i = ListView_GetNextItem( pInfo->hwndLvDevices, i, LVNI_ALL )) >= 0) { DTLNODE* pNode; PBLINK* pLink; pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, i ); ASSERT( pNode ); if(NULL == pNode) { return 0; } pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); pLink->fEnabled = ListView_GetCheck( pInfo->hwndLvDevices, i ); dwCount += (pLink->fEnabled) ? 1 : 0; } } return dwCount; } VOID GeSetPhoneFields( IN PEINFO* pInfo, IN DTLNODE* pSrcLinkNode, IN BOOL fDisableAll ) // Set the phone number group box fields from the phone information in // PBLINK node 'pSrcLinkNode'. 'PInfo' is the property sheet context. // { PBLINK* pLink; DTLNODE* pPhoneNode; TRACE( "GeSetPhoneFields" ); pLink = (PBLINK* )DtlGetData( pSrcLinkNode ); ASSERT( pLink ); pPhoneNode = FirstPhoneNodeFromPhoneList( pLink->pdtllistPhones ); if (pPhoneNode) { CuSetInfo( &pInfo->cuinfo, pPhoneNode, fDisableAll ); DestroyPhoneNode( pPhoneNode ); } } VOID GeUpdateDialAnotherFirstState( IN PEINFO* pInfo ) // Update the prequisite entry controls. 'PInfo' is the property sheet // context. // { if (Button_GetCheck( pInfo->hwndCbDialAnotherFirst )) { GeFillLbDialAnotherFirst( pInfo, FALSE ); EnableWindow( pInfo->hwndLbDialAnotherFirst, TRUE ); } else { GeClearLbDialAnotherFirst( pInfo->hwndLbDialAnotherFirst ); EnableWindow( pInfo->hwndLbDialAnotherFirst, FALSE ); } } VOID GeUpdatePhoneNumberFields( IN PEINFO* pInfo, IN BOOL fSharedToggle ) // Called when anything affecting the Phone Number group of controls // occurs. 'PInfo' is the property sheet context. 'FSharedToggle' is set // when the update is due to the toggling of the shared phone number // checkbox. // { INT i; BOOL fShared; DTLNODE* pNode; PBLINK* pLink; TRACE( "GeUpdatePhoneNumberFields" ); if (pInfo->pArgs->fMultipleDevices) { fShared = Button_GetCheck( pInfo->hwndCbSharedPhoneNumbers ); } else { fShared = TRUE; ASSERT( !fSharedToggle ); } if (pInfo->iDeviceSelected >= 0) { // A device was previously selected. // pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, pInfo->iDeviceSelected ); ASSERT( pNode ); if(NULL == pNode) { return; } if (fShared) { if (fSharedToggle) { // Shared-mode just toggled on. Update the selected node from // the controls, then copy it's phone settings to the shared // node. // GeGetPhoneFields( pInfo, pNode ); CopyLinkPhoneNumberInfo( pInfo->pArgs->pSharedNode, pNode ); } else { // Update the shared node from the controls. // GeGetPhoneFields( pInfo, pInfo->pArgs->pSharedNode ); } } else { if (fSharedToggle) { // Shared-mode just toggled off. Update the shared node from // the controls, then copy it's phone settings to the selected // node. // GeGetPhoneFields( pInfo, pInfo->pArgs->pSharedNode ); CopyLinkPhoneNumberInfo( pNode, pInfo->pArgs->pSharedNode ); } else { // Update the previously selected node from the controls. // GeGetPhoneFields( pInfo, pNode ); } } } // Load the phone number fields and title with the phone number for the // selected link. Save the selected device index in the context block so // we'll know where to swap out the phone number when the selection // changes. // i = ListView_GetNextItem( pInfo->hwndLvDevices, -1, LVIS_SELECTED ); pInfo->iDeviceSelected = i; if (i < 0) { // No device is currently selected. This occurs because a new // selection generates first an "unselect" event, then a separate // "select" event. // return; } // Set the phone number fields including group box title, all // enabling/disabling, and "blanked" handling of area code and country // code. The entire phone number group is disabled when in separate // number mode with the selected device unchecked. // if (fShared) { pInfo->pCurLinkNode = pInfo->pArgs->pSharedNode; GeUpdatePhoneNumberTitle( pInfo, NULL ); GeSetPhoneFields( pInfo, pInfo->pArgs->pSharedNode, FALSE ); } else { pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, i ); ASSERT( pNode ); if(NULL == pNode) { return; } pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); if(NULL == pLink) { return; } pInfo->pCurLinkNode = pNode; GeUpdatePhoneNumberTitle( pInfo, pLink->pbport.pszDevice ); GeSetPhoneFields( pInfo, pNode, !(ListView_GetCheck( pInfo->hwndLvDevices, i )) ); } // When the enabled device count falls below 2 the "Multiple Devices" // group box and contained controls on the Options page are disabled. If // 2 or above it is enabled. // if (pInfo->hwndOe && pInfo->pArgs->fMultipleDevices) { DWORD cChecked; cChecked = ListView_GetCheckedCount( pInfo->hwndLvDevices ); OeEnableMultipleDeviceGroup( pInfo, (cChecked > 1) ); } } VOID GeUpdatePhoneNumberTitle( IN PEINFO* pInfo, IN TCHAR* pszDevice ) // Update the Phone Number group box title based on the "share" mode. // 'PInfo' is the property sheet context. 'PszDevice' is the device name // string to display in non-shared mode or NULL in shared mode. // { if (!pInfo->hwndGbPhoneNumber) { return; } if (pszDevice) { TCHAR* psz; TCHAR* pszFormat; // Set the individual title, e.g. "Phone number for K-Tel 28.8 // Fax/Plus". // pszFormat = PszFromId( g_hinstDll, SID_LinkPhoneNumber ); if (pszFormat) { psz = Malloc( (lstrlen( pszFormat ) + lstrlen( pszDevice )) * sizeof(TCHAR) ); if (psz) { wsprintf( psz, pszFormat, pszDevice ); SetWindowText( pInfo->hwndGbPhoneNumber, psz ); Free( psz ); } Free( pszFormat ); } } else { TCHAR* psz; // Set the shared title, e.g. "Phone number". // psz = PszFromId( g_hinstDll, SID_SharedPhoneNumber ); if (psz) { SetWindowText( pInfo->hwndGbPhoneNumber, psz ); Free( psz ); } } } VOID GeUpdateUpDownButtons( IN PEINFO* pInfo ) // Update the enable/disable and corresponding icon for the // move-up/move-down buttons. Moves focus and default button as // necessary. 'PInfo' is the property sheet context. // { INT iSel; INT cItems; BOOL fSel; if (!pInfo->pArgs->fMultipleDevices) { return; } iSel = ListView_GetNextItem( pInfo->hwndLvDevices, -1, LVNI_SELECTED ); fSel = (iSel >= 0); cItems = ListView_GetItemCount( pInfo->hwndLvDevices ); // "Up" button, enabled if there is an item above. // if (iSel > 0) { EnableWindow( pInfo->hwndPbUp, TRUE ); SendMessage( pInfo->hwndPbUp, BM_SETIMAGE, IMAGE_ICON, (LPARAM )pInfo->hiconUpArr ); } else { EnableWindow( pInfo->hwndPbUp, FALSE ); SendMessage( pInfo->hwndPbUp, BM_SETIMAGE, IMAGE_ICON, (LPARAM )pInfo->hiconUpArrDis ); } // "Down" button, enabled if there is an item below. // if (fSel && (iSel < cItems - 1)) { EnableWindow( pInfo->hwndPbDown, TRUE ); SendMessage( pInfo->hwndPbDown, BM_SETIMAGE, IMAGE_ICON, (LPARAM )pInfo->hiconDnArr ); } else { EnableWindow( pInfo->hwndPbDown, FALSE ); SendMessage( pInfo->hwndPbDown, BM_SETIMAGE, IMAGE_ICON, (LPARAM )pInfo->hiconDnArrDis ); } // if the focus button is disabled, move focus to the ListView and make OK // the default button. // if (!IsWindowEnabled( GetFocus() )) { SetFocus( pInfo->hwndLvDevices ); Button_MakeDefault( pInfo->hwndDlg, GetDlgItem( pInfo->hwndDlg, IDOK ) ); } } //---------------------------------------------------------------------------- // Options property page // Listed alphabetically following dialog proc //---------------------------------------------------------------------------- INT_PTR CALLBACK OeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the Options page of the Entry property sheet. // Parameters and return value are as described for standard windows // 'DialogProc's. // { #if 0 TRACE4( "OeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif switch (unMsg) { case WM_INITDIALOG: { return OeInit( hwnd ); } case WM_HELP: case WM_CONTEXTMENU: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } if (pInfo->pArgs->fRouter) { ContextHelp( g_adwOeRouterHelp, hwnd, unMsg, wparam, lparam ); } else { ContextHelp( g_adwOeHelp, hwnd, unMsg, wparam, lparam ); } break; } case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } return OeCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } case WM_NOTIFY: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } switch (((NMHDR* )lparam)->code) { case PSN_SETACTIVE: { // Because of inter-page dependencies on the 'fAutoLogon' // flag the User/password and subordinate checkbox states // must be reinitialized at each activation. // OeUpdateUserPwState( pInfo ); break; } } break; } } return FALSE; } BOOL OeCommand( 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. // { TRACE3( "OeCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl ); switch (wId) { case CID_OE_CB_PreviewUserPw: { pInfo->pArgs->pEntry->fPreviewUserPw = Button_GetCheck( pInfo->hwndCbPreviewUserPw ); OeUpdateUserPwState( pInfo ); return TRUE; } case CID_OE_CB_PreviewDomain: { pInfo->pArgs->pEntry->fPreviewDomain = Button_GetCheck( pInfo->hwndCbPreviewDomain ); return TRUE; } case CID_OE_PB_Configure: { MultiLinkDialingDlg( pInfo->hwndDlg, pInfo->pArgs->pEntry ); return TRUE; } case CID_OE_PB_X25: { OeX25( pInfo ); return TRUE; } case CID_OE_PB_Tunnel: { OeTunnel( pInfo ); return TRUE; } case CID_OE_LB_MultipleDevices: { pInfo->pArgs->pEntry->dwDialMode = (DWORD)ComboBox_GetItemData( pInfo->hwndLbMultipleDevices, ComboBox_GetCurSel( pInfo->hwndLbMultipleDevices ) ); EnableWindow( pInfo->hwndPbConfigureDialing, !!(pInfo->pArgs->pEntry->dwDialMode == RASEDM_DialAsNeeded) ); return TRUE; } case CID_OE_RB_Persistent: { switch (wNotification) { case BN_CLICKED: { ComboBox_SetCurSel( pInfo->hwndLbIdleTimes, 0 ); EnableWindow( pInfo->hwndLbIdleTimes, FALSE ); return TRUE; } } break; } case CID_OE_RB_DemandDial: { switch (wNotification) { case BN_CLICKED: { EnableWindow( pInfo->hwndLbIdleTimes, TRUE ); return TRUE; } } break; } case CID_OE_PB_Callback: { RouterCallbackDlg ( pInfo->hwndOe, pInfo->pArgs ); return TRUE; } } return FALSE; } VOID OeEnableMultipleDeviceGroup( IN PEINFO* pInfo, IN BOOL fEnable ) // Enable/disable the Multiple Devices groupbox and all controls it // contains based on 'fEnable'. 'PInfo' is the property sheet context. // { EnableWindow( pInfo->hwndGbMultipleDevices, fEnable ); EnableWindow( pInfo->hwndLbMultipleDevices, fEnable ); EnableWindow( pInfo->hwndPbConfigureDialing, (fEnable && !!(pInfo->pArgs->pEntry->dwDialMode == RASEDM_DialAsNeeded)) ); } BOOL OeInit( 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; LBTABLEITEM* pItem; HWND hwndLb; INT i; INT iSel; HWND hwndUdRedialAttempts; static LBTABLEITEM aRedialTimes[] = { SID_Time1s, 1, SID_Time3s, 3, SID_Time5s, 5, SID_Time10s, 10, SID_Time30s, 30, SID_Time1m, 60, SID_Time2m, 120, SID_Time5m, 300, SID_Time10m, RAS_RedialPause10m, 0, 0 }; static LBTABLEITEM aIdleTimes[] = { SID_TimeNever, 0, SID_Time1m, 60, SID_Time5m, 300, SID_Time10m, 600, SID_Time20m, 1200, //Add for whistler bug 307969 SID_Time30m, 1800, SID_Time1h, 3600, SID_Time2h, 7200, SID_Time4h, 14400, SID_Time8h, 28800, SID_Time24h, 86400, 0, 0 }; static LBTABLEITEM aMultipleDeviceOptions[] = { SID_DialOnlyFirst, 0, SID_DialAll, RASEDM_DialAll, SID_DialNeeded, RASEDM_DialAsNeeded, 0, 0 }; TRACE( "OeInit" ); pInfo = PeContext( hwndPage ); if (!pInfo) { return TRUE; } pEntry = pInfo->pArgs->pEntry; // Initialize page-specific context information. // pInfo->hwndOe = hwndPage; // Initialize 'Dialing options' group box. // if (!pInfo->pArgs->fRouter) { pInfo->hwndCbDisplayProgress = GetDlgItem( hwndPage, CID_OE_CB_DisplayProgress ); ASSERT( pInfo->hwndCbDisplayProgress ); Button_SetCheck( pInfo->hwndCbDisplayProgress, pEntry->fShowDialingProgress ); pInfo->hwndCbPreviewUserPw = GetDlgItem( hwndPage, CID_OE_CB_PreviewUserPw ); ASSERT( pInfo->hwndCbPreviewUserPw ); pInfo->fPreviewUserPw = pEntry->fPreviewUserPw; Button_SetCheck( pInfo->hwndCbPreviewUserPw, pInfo->fPreviewUserPw ); pInfo->hwndCbPreviewDomain = GetDlgItem( hwndPage, CID_OE_CB_PreviewDomain ); ASSERT( pInfo->hwndCbPreviewDomain ); pInfo->fPreviewDomain = pEntry->fPreviewDomain; Button_SetCheck( pInfo->hwndCbPreviewDomain, pInfo->fPreviewDomain ); if (pEntry->dwType == RASET_Phone) { pInfo->hwndCbPreviewNumber = GetDlgItem( hwndPage, CID_OE_CB_PreviewNumber ); ASSERT( pInfo->hwndCbPreviewNumber ); Button_SetCheck( pInfo->hwndCbPreviewNumber, pEntry->fPreviewPhoneNumber ); } } // Initialize 'Redialing options' group box. In the 'fRouter' case this // includes both the 'Dialing policy' and 'Connection type' group boxes. // { pInfo->hwndEbRedialAttempts = GetDlgItem( hwndPage, CID_OE_EB_RedialAttempts ); ASSERT( pInfo->hwndEbRedialAttempts ); // Redial attempts. Note that the RAS API and phonebook allow redials // up to RAS_MaxRedialCount (999999999). However, it was decided this // many redials didn't make sense. Thus we have limited the UI to a max // of MAX_UI_REDIAL_ATTEMPTS (99) redials even though through the API // or an upgraded phonebook entry may have more. // hwndUdRedialAttempts = CreateUpDownControl( WS_CHILD + WS_VISIBLE + WS_BORDER + UDS_SETBUDDYINT + UDS_ALIGNRIGHT + UDS_NOTHOUSANDS + UDS_ARROWKEYS, 0, 0, 0, 0, hwndPage, 100, g_hinstDll, pInfo->hwndEbRedialAttempts, MAX_UI_REDIAL_ATTEMPTS, 0, 0 ); ASSERT( hwndUdRedialAttempts ); Edit_LimitText( pInfo->hwndEbRedialAttempts, MAX_UI_REDIAL_CHARS ); SetDlgItemInt( hwndPage, CID_OE_EB_RedialAttempts, pEntry->dwRedialAttempts, FALSE ); // Redial times. // pInfo->hwndLbRedialTimes = GetDlgItem( hwndPage, CID_OE_LB_RedialTimes ); ASSERT( pInfo->hwndLbRedialTimes ); { iSel = -1; for (pItem = aRedialTimes, i = 0; pItem->sidItem; ++pItem, ++i ) { ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbRedialTimes, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData )); if (iSel < 0 && pEntry->dwRedialSeconds <= pItem->dwData) { iSel = i; ComboBox_SetCurSel( pInfo->hwndLbRedialTimes, iSel ); } } if (iSel < 0) { ComboBox_SetCurSel( pInfo->hwndLbRedialTimes, i - 1 ); } } // Idle times. // pInfo->hwndLbIdleTimes = GetDlgItem( hwndPage, CID_OE_LB_IdleTimes ); ASSERT( pInfo->hwndLbIdleTimes ); { if (pEntry->lIdleDisconnectSeconds < 0) { pEntry->lIdleDisconnectSeconds = 0; } iSel = -1; for (pItem = aIdleTimes, i = 0; pItem->sidItem; ++pItem, ++i ) { ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbIdleTimes, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData)); if (iSel < 0 && pEntry->lIdleDisconnectSeconds <= (LONG )pItem->dwData) { iSel = i; ComboBox_SetCurSel( pInfo->hwndLbIdleTimes, iSel ); } } if (iSel < 0) { ComboBox_SetCurSel( pInfo->hwndLbIdleTimes, i - 1 ); } } if (pInfo->pArgs->fRouter) { HWND hwndRb; //for whistler bug 294271, initialize the window handlers for //multiple device group gangz // pInfo->hwndGbMultipleDevices = GetDlgItem( hwndPage, CID_OE_GB_MultipleDevices ); ASSERT( pInfo->hwndGbMultipleDevices ); pInfo->hwndLbMultipleDevices = GetDlgItem( hwndPage, CID_OE_LB_MultipleDevices ); ASSERT( pInfo->hwndLbMultipleDevices ); pInfo->hwndPbConfigureDialing = GetDlgItem( hwndPage, CID_OE_PB_Configure ); ASSERT( pInfo->hwndPbConfigureDialing ); // Connection type radio buttons. // pInfo->hwndRbDemandDial = GetDlgItem( hwndPage, CID_OE_RB_DemandDial ); ASSERT( pInfo->hwndRbDemandDial ); pInfo->hwndRbPersistent = GetDlgItem( hwndPage, CID_OE_RB_Persistent ); ASSERT( pInfo->hwndRbPersistent ); hwndRb = (pEntry->fRedialOnLinkFailure) ? pInfo->hwndRbPersistent : pInfo->hwndRbDemandDial; SendMessage( hwndRb, BM_CLICK, 0, 0 ); } else { // Redial on link failure // pInfo->hwndCbRedialOnDrop = GetDlgItem( hwndPage, CID_OE_CB_RedialOnDrop ); ASSERT( pInfo->hwndCbRedialOnDrop ); Button_SetCheck( pInfo->hwndCbRedialOnDrop, pEntry->fRedialOnLinkFailure ); } } // Initialize 'Multiple devices' group box. // if (pEntry->dwType == RASET_Phone) { pInfo->hwndGbMultipleDevices = GetDlgItem( hwndPage, CID_OE_GB_MultipleDevices ); ASSERT( pInfo->hwndGbMultipleDevices ); pInfo->hwndLbMultipleDevices = GetDlgItem( hwndPage, CID_OE_LB_MultipleDevices ); ASSERT( pInfo->hwndLbMultipleDevices ); pInfo->hwndPbConfigureDialing = GetDlgItem( hwndPage, CID_OE_PB_Configure ); ASSERT( pInfo->hwndPbConfigureDialing ); { iSel = -1; for (pItem = aMultipleDeviceOptions, i = 0; pItem->sidItem; ++pItem, ++i ) { ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbMultipleDevices, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData)); if (pEntry->dwDialMode == pItem->dwData) { iSel = i; ComboBox_SetCurSel( pInfo->hwndLbMultipleDevices, iSel ); } } if (iSel < 0) { ComboBox_SetCurSel( pInfo->hwndLbMultipleDevices, 0 ); } } if (pInfo->pArgs->fMultipleDevices) { DWORD cChecked; // When the enabled device count falls below 2 the "Multiple // Devices" group box and contained controls are disabled. If 2 // or above it is enabled. // if (pInfo->hwndLvDevices) { cChecked = ListView_GetCheckedCount( pInfo->hwndLvDevices ); OeEnableMultipleDeviceGroup( pInfo, (cChecked > 1) ); } } else { ShowWindow( pInfo->hwndGbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndLbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndPbConfigureDialing, SW_HIDE ); } } else if (pInfo->pArgs->fRouter && pEntry->dwType == RASET_Vpn) { // Make sure that a VPN demand dial interface can't be configured for // multilink. // ComboBox_SetCurSel( pInfo->hwndLbMultipleDevices, 0 ); ShowWindow( pInfo->hwndGbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndLbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndPbConfigureDialing, SW_HIDE ); } else if (pEntry->dwType == RASET_Broadband) { // Make sure that broadband connections can't be multilinked since // it is not possible to select multiple ports. // ComboBox_SetCurSel( pInfo->hwndLbMultipleDevices, 0 ); ShowWindow( pInfo->hwndGbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndLbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndPbConfigureDialing, SW_HIDE ); } else if ( pEntry->dwType == RASET_Direct ) { //for whistler bug 294271, initialize the window handlers for //multiple device group gangz // ShowWindow( pInfo->hwndGbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndLbMultipleDevices, SW_HIDE ); ShowWindow( pInfo->hwndPbConfigureDialing, SW_HIDE ); } // Bug 261692: Don't show X.25 button unless "phone" type entry. // if (pInfo->pArgs->fRouter && pEntry->dwType != RASET_Phone) { pInfo->hwndPbX25 = GetDlgItem( hwndPage, CID_OE_PB_X25 ); ASSERT( pInfo->hwndPbX25 ); ShowWindow( pInfo->hwndPbX25, SW_HIDE ); EnableWindow( pInfo->hwndPbX25, FALSE ); } return TRUE; } VOID OeTunnel( IN PEINFO* pInfo ) // Called when the "Virtual (tunnel) connection" button is pressed to // chain the VPN add entry wizard. // { //!!! } VOID OeUpdateUserPwState( IN PEINFO* pInfo ) // Called to update the enabled/disabled save/restore state of the // User/password and Domain checkboxes. // { PBENTRY* pEntry; pEntry = pInfo->pArgs->pEntry; EnableCbWithRestore( pInfo->hwndCbPreviewUserPw, !pEntry->fAutoLogon, FALSE, &pInfo->fPreviewUserPw ); EnableCbWithRestore( pInfo->hwndCbPreviewDomain, !pEntry->fAutoLogon, FALSE, &pInfo->fPreviewDomain ); } VOID OeX25( IN PEINFO* pInfo ) // Called when the X.25 button is pressed to popup the X.25 settings // dialog. // { DTLNODE* pNode; PBLINK* pLink; BOOL fLocalPad; INT iSel; // Figure out if the selected device is a local PAD device. // fLocalPad = FALSE; iSel = ListView_GetNextItem( pInfo->hwndLvDevices, -1, LVNI_SELECTED ); if (iSel >= 0) { pNode = (DTLNODE* )ListView_GetParamPtr( pInfo->hwndLvDevices, iSel ); ASSERT( pNode ); if(NULL == pNode) { return; } pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); if (pLink->pbport.pbdevicetype == PBDT_Pad) { fLocalPad = TRUE; } } // Popup the X.25 dialog which saves directly to the common context // 'pEntry' if user makes changes. // X25LogonSettingsDlg( pInfo->hwndDlg, fLocalPad, pInfo->pArgs->pEntry ); } //---------------------------------------------------------------------------- // Security property page // Listed alphabetically following dialog proc //---------------------------------------------------------------------------- INT_PTR CALLBACK LoDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the Security page of the Entry property sheet // "Lo" is for Logon, the original name of this page. Parameters and // return value are as described for standard windows 'DialogProc's. // { #if 0 TRACE4( "LoDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif switch (unMsg) { case WM_INITDIALOG: { return LoInit( hwnd ); } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwLoHelp, hwnd, unMsg, wparam, lparam ); break; } case WM_COMMAND: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } return LoCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } case WM_NOTIFY: { PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } switch (((NMHDR* )lparam)->code) { case PSN_SETACTIVE: { // Because of inter-page dependencies on the framing type, // the typical and advanced sections must be reinitialized // at each activation. // BOOL fEnabled; //This is for pre-shared key bug // fEnabled = ( VS_PptpOnly != pInfo->pArgs->pEntry->dwVpnStrategy ); EnableWindow( pInfo->hwndPbIPSec, fEnabled ); pInfo->fAuthRbInitialized = FALSE; LoRefreshSecuritySettings( pInfo ); break; } } break; } } return FALSE; } BOOL LoCommand( 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. // { TRACE3( "LoCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl ); switch (wId) { case CID_LO_LB_Auths: { switch (wNotification) { case CBN_SELCHANGE: { LoLbAuthsSelChange( pInfo ); return TRUE; } } break; } case CID_LO_CB_UseWindowsPw: { switch (wNotification) { case BN_CLICKED: { // Necessary to save 'fAutoLogon' setting immediately as // there is an inter-page dependency with the Option page // 'fPreviewUserPw' and subordinate controls. // LoSaveTypicalAuthSettings( pInfo ); return TRUE; } } break; } case CID_LO_RB_TypicalSecurity: { switch (wNotification) { case BN_CLICKED: { if (!pInfo->fAuthRbInitialized) { pInfo->fAuthRbInitialized = TRUE; } pInfo->pArgs->pEntry->dwAuthRestrictions &= ~(AR_F_AuthCustom); LoEnableSecuritySettings( pInfo, TRUE, FALSE ); return TRUE; } } break; } case CID_LO_RB_AdvancedSecurity: { switch (wNotification) { case BN_CLICKED: { if (!pInfo->fAuthRbInitialized) { pInfo->fAuthRbInitialized = TRUE; } else { // Save the "typical" settings as they will be used as // defaults should user decide to invoke the advanced // security dialog. // LoSaveTypicalAuthSettings( pInfo ); } pInfo->pArgs->pEntry->dwAuthRestrictions |= AR_F_AuthCustom; LoEnableSecuritySettings( pInfo, FALSE, TRUE ); return TRUE; } } break; } case CID_LO_PB_Advanced: { switch (wNotification) { case BN_CLICKED: { // At this point, the 'pEntry' authentication settings // match the current "typical" settings, which the // advanced dialog uses as defaults. // AdvancedSecurityDlg( pInfo->hwndDlg, pInfo->pArgs ); return TRUE; } } break; } case CID_LO_PB_IPSec: { switch (wNotification) { case BN_CLICKED: { IPSecPolicyDlg( pInfo->hwndDlg, pInfo->pArgs ); return TRUE; } } break; } case CID_LO_CB_RunScript: { if (SuScriptsCbHandler( &pInfo->suinfo, wNotification )) { return TRUE; } break; } case CID_LO_PB_Edit: { if (SuEditPbHandler( &pInfo->suinfo, wNotification )) { return TRUE; } break; } case CID_LO_PB_Browse: { if (SuBrowsePbHandler( &pInfo->suinfo, wNotification )) { return TRUE; } break; } } return FALSE; } VOID LoEnableSecuritySettings( IN PEINFO* pInfo, IN BOOL fTypical, IN BOOL fAdvanced ) // Enables/disables the typical or advanced security settings based on // caller's 'fTypical' and 'fAdvanced' flags. If neither flag is set all // controls including the frames and radio buttons are disabled. Both // flags may not be set. 'PInfo' is the property sheet context. // { BOOL fEither; ASSERT( !(fTypical && fAdvanced) ); fEither = (fTypical || fAdvanced); EnableWindow( pInfo->hwndGbSecurityOptions, fEither ); EnableWindow( pInfo->hwndRbTypicalSecurity, fEither ); EnableWindow( pInfo->hwndStAuths, fTypical ); EnableLbWithRestore( pInfo->hwndLbAuths, fTypical, &pInfo->iLbAuths ); // Note: "Use Windows password" and "require encryption" checkbox updates // are triggered by the EnableLbWithRestore above. EnableWindow( pInfo->hwndRbAdvancedSecurity, fEither ); EnableWindow( pInfo->hwndStAdvancedText, fAdvanced ); EnableWindow( pInfo->hwndPbAdvanced, fAdvanced ); } VOID LoFillLbAuths( IN PEINFO* pInfo ) // Fill the authentication list box and set the selection based on the // setting in the phonebook entry. 'PInfo' is the property sheet context. // This routine should be called only once. // { INT i; LBTABLEITEM* pItem; LBTABLEITEM* pItems; PBENTRY* pEntry; LBTABLEITEM aItemsPhone[] = { SID_AuthUnsecured, TA_Unsecure, SID_AuthSecured, TA_Secure, SID_AuthCardOrCert, TA_CardOrCert, 0, 0 }; LBTABLEITEM aItemsVpn[] = { SID_AuthSecured, TA_Secure, SID_AuthCardOrCert, TA_CardOrCert, 0, 0 }; LBTABLEITEM aItemsPhoneRouter[] = { SID_AuthUnsecured, TA_Unsecure, SID_AuthSecured, TA_Secure, 0, 0 }; LBTABLEITEM aItemsVpnRouter[] = { SID_AuthSecured, TA_Secure, 0, 0 }; pEntry = pInfo->pArgs->pEntry; if (pEntry->dwType == RASET_Vpn) { pItems = (pInfo->pArgs->fRouter) ? aItemsVpnRouter : aItemsVpn; } else { pItems = (pInfo->pArgs->fRouter) ? aItemsPhoneRouter : aItemsPhone; } for (pItem = pItems; pItem->sidItem; ++pItem) { i = ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbAuths, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData)); if (pEntry->dwTypicalAuth == pItem->dwData) { ComboBox_SetCurSelNotify( pInfo->hwndLbAuths, i ); } } if (ComboBox_GetCurSel( pInfo->hwndLbAuths ) < 0) { ComboBox_SetCurSelNotify( pInfo->hwndLbAuths, 0 ); } } BOOL LoInit( 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( "LoInit" ); pInfo = PeContext( hwndPage ); if (!pInfo) { return TRUE; } pEntry = pInfo->pArgs->pEntry; // Initialize page-specific context information. // pInfo->hwndLo = hwndPage; pInfo->hwndGbSecurityOptions = GetDlgItem( hwndPage, CID_LO_GB_SecurityOptions ); ASSERT( pInfo->hwndGbSecurityOptions ); pInfo->hwndRbTypicalSecurity = GetDlgItem( hwndPage, CID_LO_RB_TypicalSecurity ); ASSERT( pInfo->hwndRbTypicalSecurity ); pInfo->hwndStAuths = GetDlgItem( hwndPage, CID_LO_ST_Auths ); ASSERT( pInfo->hwndStAuths ); pInfo->hwndLbAuths = GetDlgItem( hwndPage, CID_LO_LB_Auths ); ASSERT( pInfo->hwndLbAuths ); pInfo->hwndCbUseWindowsPw = GetDlgItem( hwndPage, CID_LO_CB_UseWindowsPw ); ASSERT( pInfo->hwndCbUseWindowsPw ); pInfo->hwndCbEncryption = GetDlgItem( hwndPage, CID_LO_CB_Encryption ); ASSERT( pInfo->hwndCbEncryption ); pInfo->hwndRbAdvancedSecurity = GetDlgItem( hwndPage, CID_LO_RB_AdvancedSecurity ); ASSERT( pInfo->hwndRbAdvancedSecurity ); pInfo->hwndStAdvancedText = GetDlgItem( hwndPage, CID_LO_ST_AdvancedText ); ASSERT( pInfo->hwndStAdvancedText ); pInfo->hwndPbAdvanced = GetDlgItem( hwndPage, CID_LO_PB_Advanced ); ASSERT( pInfo->hwndPbAdvanced ); // //for VPN's security page show IPSec Policy // for whistler bug 193987 // if ( pInfo->pArgs->pEntry->dwType == RASET_Vpn ) { BOOL fEnabled; pInfo->hwndPbIPSec = GetDlgItem( hwndPage, CID_LO_PB_IPSec ); ASSERT( pInfo->hwndPbIPSec ); // gangz //If it is for a remote Win2k server's Demand Dialer //dont show the IPSec Policy stuff, because W2k didnt //implement this. // if ( pInfo->pArgs->fW2kRouter ) { ShowWindow( pInfo->hwndPbIPSec, FALSE ); } else { fEnabled = ( VS_PptpOnly != pInfo->pArgs->pEntry->dwVpnStrategy ); EnableWindow( pInfo->hwndPbIPSec, fEnabled ); } //for the IPSec Policy dialog, fPSKCached = TRUE means the user already //go to the IPSec Policy dialog and saved a PSK gangz // pInfo->pArgs->fPSKCached = FALSE; //gangz: for bug# 276452 //On a Server OS, the help message for this IPSec pushbutton //should be different from that for a Non-server OS, //so change its help ID when neeeded. // if ( IsServerOS() ) { DWORD * p = (DWORD *)g_adwLoHelp; while( p ) { if ( (p[0] == 0) && ( p[1] == 0 ) ) { break; } if ( (p[0] == CID_LO_PB_IPSec) && (p[1] == HID_LO_PB_IPSec) ) { p[1] = HID_LO_PB_IPSecServer; break; } p+=2; } } } else { pInfo->hwndGbScripting = GetDlgItem( hwndPage, CID_LO_GB_Scripting ); ASSERT( pInfo->hwndGbScripting ); pInfo->hwndCbRunScript = GetDlgItem( hwndPage, CID_LO_CB_RunScript ); ASSERT( pInfo->hwndCbRunScript ); pInfo->hwndCbTerminal = GetDlgItem( hwndPage, CID_LO_CB_Terminal ); ASSERT( pInfo->hwndCbTerminal ); pInfo->hwndLbScripts = GetDlgItem( hwndPage, CID_LO_LB_Scripts ); ASSERT( pInfo->hwndLbScripts ); pInfo->hwndPbEdit = GetDlgItem( hwndPage, CID_LO_PB_Edit ); ASSERT( pInfo->hwndPbEdit ); pInfo->hwndPbBrowse = GetDlgItem( hwndPage, CID_LO_PB_Browse ); ASSERT( pInfo->hwndPbBrowse ); } // Initialize the page controls. Note that the page activation event // immediately after this initialization triggers the final security // setting enabling/disabling and does any "restore caching". While this // initialization sets the check values and list selection to bootstrap // the "restore caching", these settings may be adjusted by the activation // refresh. // if (pInfo->pArgs->fRouter) { // The "Use Windows credentials" option is removed in the demand-dial // case. // pInfo->fUseWindowsPw = FALSE; Button_SetCheck( pInfo->hwndCbUseWindowsPw, FALSE ); EnableWindow ( pInfo->hwndCbUseWindowsPw, FALSE ); ShowWindow (pInfo->hwndCbUseWindowsPw, SW_HIDE ); } else { pInfo->fUseWindowsPw = pEntry->fAutoLogon; Button_SetCheck( pInfo->hwndCbUseWindowsPw, pInfo->fUseWindowsPw ); } pInfo->fEncryption = (pEntry->dwDataEncryption != DE_None && pEntry->dwDataEncryption != DE_IfPossible); Button_SetCheck( pInfo->hwndCbEncryption, pInfo->fEncryption ); // Fill authentiction list and set selection, which triggers all // appropriate enabling/disabling. // LoFillLbAuths( pInfo ); if ((pInfo->pArgs->pEntry->dwType != RASET_Vpn) && (pInfo->pArgs->pEntry->dwType != RASET_Direct) && (pInfo->pArgs->pEntry->dwType != RASET_Broadband)) //&& !pInfo->pArgs->fRouter) { // Set up the after-dial scripting controls. // SuInit( &pInfo->suinfo, pInfo->hwndCbRunScript, pInfo->hwndCbTerminal, pInfo->hwndLbScripts, pInfo->hwndPbEdit, pInfo->hwndPbBrowse, pInfo->pArgs->fRouter ? SU_F_DisableTerminal : 0); pInfo->fSuInfoInitialized = TRUE; SuSetInfo( &pInfo->suinfo, pEntry->fScriptAfter, pEntry->fScriptAfterTerminal, pEntry->pszScriptAfter ); } else { // Disable/hide the after-dial scripting controls. // for VPN there is no need to do this Disable/hide operation // if (pInfo->pArgs->pEntry->dwType != RASET_Vpn) { EnableWindow( pInfo->hwndGbScripting, FALSE ); ShowWindow( pInfo->hwndGbScripting, SW_HIDE ); EnableWindow( pInfo->hwndCbRunScript, FALSE ); ShowWindow( pInfo->hwndCbRunScript, SW_HIDE ); EnableWindow( pInfo->hwndCbTerminal, FALSE ); ShowWindow( pInfo->hwndCbTerminal, SW_HIDE ); EnableWindow( pInfo->hwndLbScripts, FALSE ); ShowWindow( pInfo->hwndLbScripts, SW_HIDE ); EnableWindow( pInfo->hwndPbEdit, FALSE ); ShowWindow( pInfo->hwndPbEdit, SW_HIDE ); EnableWindow( pInfo->hwndPbBrowse, FALSE ); ShowWindow( pInfo->hwndPbBrowse, SW_HIDE ); } } if (pInfo->pArgs->fRouter) { EnableWindow( pInfo->hwndCbTerminal, FALSE ); ShowWindow( pInfo->hwndCbTerminal, SW_HIDE ); } return TRUE; } VOID LoLbAuthsSelChange( IN PEINFO* pInfo ) // Called when the selection in the authentication drop list is changed. // { INT iSel; DWORD dwTaCode; // Retrieve the bitmask of authentication protocols associated with the // selected authentication level. // iSel = ComboBox_GetCurSel( pInfo->hwndLbAuths ); if (iSel < 0) { dwTaCode = 0; } else { dwTaCode = (DWORD )ComboBox_GetItemData( pInfo->hwndLbAuths, iSel ); } if (!pInfo->pArgs->fRouter) { // Update the "Use Windows NT credentials" checkbox. Per the spec, it // is enabled only for "require secure password", though the real // requirement is that MSCHAP (provides NT-style credentials) gets // negotiated. // EnableCbWithRestore( pInfo->hwndCbUseWindowsPw, (dwTaCode == TA_Secure), FALSE, &pInfo->fUseWindowsPw ); } // Update the "Require data encryption" checkbox. Per the spec, it is // enabled unless "allow unsecured password" is selected, though the real // requirement is that all authentication protocols in the set provide // MPPE encryption keys. // EnableCbWithRestore( pInfo->hwndCbEncryption, (dwTaCode != 0 && dwTaCode != TA_Unsecure), FALSE, &pInfo->fEncryption ); } VOID LoRefreshSecuritySettings( IN PEINFO* pInfo ) // Sets the contents and state of all typical and advanced security // setting fields. // { if (pInfo->pArgs->pEntry->dwBaseProtocol & BP_Slip) { // For SLIP framing, all the typical and advanced controls are // disabled and the radio buttons show no selection. // Button_SetCheck( pInfo->hwndRbTypicalSecurity, FALSE ); Button_SetCheck( pInfo->hwndRbAdvancedSecurity, FALSE ); LoEnableSecuritySettings( pInfo, FALSE, FALSE ); if (pInfo->fShowSlipPopup) { // Time to show the one-shot informational about SLIP not doing // any in-protocol authentication or encryption. // MsgDlg( pInfo->hwndDlg, SID_NoAuthForSlip, NULL ); pInfo->fShowSlipPopup = FALSE; } } else { HWND hwndRb; // For PPP framing, select the appropriate security setting radio // button which triggers additional enabling/disabling of the framed // controls. // if (pInfo->pArgs->pEntry->dwAuthRestrictions & AR_F_AuthCustom) { hwndRb = pInfo->hwndRbAdvancedSecurity; } else { hwndRb = pInfo->hwndRbTypicalSecurity; } SendMessage( hwndRb, BM_CLICK, 0, 0 ); } } VOID LoSaveTypicalAuthSettings( IN PEINFO* pInfo ) // Save the values in the "typical" authentication controls to the // phonebook entry. 'PInfo' is the property sheet context. // { PBENTRY* pEntry; INT iSel; pEntry = pInfo->pArgs->pEntry; iSel = ComboBox_GetCurSel( pInfo->hwndLbAuths ); if (iSel >= 0) { pEntry->dwTypicalAuth = (DWORD) ComboBox_GetItemData( pInfo->hwndLbAuths, iSel ); pEntry->dwAuthRestrictions = AuthRestrictionsFromTypicalAuth( pEntry->dwTypicalAuth ); // Set the default custom authentication key value for smart // cards. RasDial API should assume this default anyway, but we // need it before then in DialerDlgEap. // if (pEntry->dwTypicalAuth == TA_CardOrCert) { pEntry->dwCustomAuthKey = EAPCFG_DefaultKey; } else { pEntry->dwCustomAuthKey = (DWORD )-1; } } if (IsWindowEnabled( pInfo->hwndCbUseWindowsPw )) { pEntry->fAutoLogon = Button_GetCheck( pInfo->hwndCbUseWindowsPw ); } else { pEntry->fAutoLogon = FALSE; } if (IsWindowEnabled( pInfo->hwndCbEncryption )) { pEntry->dwDataEncryption = (Button_GetCheck( pInfo->hwndCbEncryption )) ? DE_Require : DE_IfPossible; } else { pEntry->dwDataEncryption = DE_IfPossible; } if (pEntry->dwDataEncryption == DE_Require && !(pEntry->dwType == RASET_Vpn && pEntry->dwVpnStrategy == VS_L2tpOnly)) { // Encryption is required and MPPE will be the encryption method // so eliminate authentication protocols that don't support it. // pEntry->dwAuthRestrictions &= ~(AR_F_AuthNoMPPE); } } //---------------------------------------------------------------------------- // Networking property page // Listed alphabetically following dialog proc //---------------------------------------------------------------------------- LVXDRAWINFO* NeLvComponentsCallback( 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 draw information. // { // Use "full row select" and other recommended options. // // Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'. // static LVXDRAWINFO info = { 1, 0, LVXDI_DxFill, { 0 } }; return &info; } INT_PTR CALLBACK NeDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the Network page of the Entry property sheet. // Parameters and return value are as described for standard windows // 'DialogProc's. // { // Filter the customized list view messages if (ListView_OwnerHandler(hwnd, unMsg, wparam, lparam, NeLvComponentsCallback)) return TRUE; switch (unMsg) { case WM_INITDIALOG: { return NeInit( hwnd ); } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwNeHelp, hwnd, unMsg, wparam, lparam ); break; } case WM_COMMAND: { PEINFO* pInfo = PeContext (hwnd); ASSERT (pInfo); switch (LOWORD(wparam)) { case CID_NE_LB_ServerType: if (CBN_SELCHANGE == HIWORD(wparam)) { NeServerTypeSelChange (pInfo); } break; case CID_NE_PB_Settings: DialogBoxParam (g_hinstDll, MAKEINTRESOURCE(DID_NE_PppSettings), hwnd, PpDlgProc, (LPARAM)pInfo); break; case CID_NE_PB_Add: NeAddComponent (pInfo); break; case CID_NE_PB_Properties: NeShowComponentProperties (pInfo); break; case CID_NE_PB_Remove: NeRemoveComponent (pInfo); break; } break; } case WM_NOTIFY: { PEINFO* pInfo = PeContext(hwnd); //!!! Hack related to PeTerm in WM_DESTROY. We still get // WM_NOTIFYs after PeTerm is called. So we commented out the // following assert and moved it into each message handler below. //ASSERT (pInfo); switch (((NMHDR*)lparam)->code) { // !!! See if base lvx.c code can handle inversion of check state on double // click. #if 0 case NM_CLICK: ASSERT (pInfo); if (CID_NE_LV_Components == ((NMHDR*)lparam)->idFrom) { NeLvClick (pInfo, FALSE); } break; #endif case NM_DBLCLK: ASSERT (pInfo); if (CID_NE_LV_Components == ((NMHDR*)lparam)->idFrom) { NeLvClick (pInfo, TRUE); } break; case LVN_ITEMCHANGED: ASSERT (pInfo); NeLvItemChanged (pInfo); break; case LVN_DELETEITEM: ASSERT (pInfo); NeLvDeleteItem (pInfo, (NM_LISTVIEW*)lparam); break; case PSN_SETACTIVE: ASSERT (pInfo); // If we couldn't get INetCfg, we can't show this page. // if (!pInfo->pNetCfg) { MsgDlg( pInfo->hwndDlg, ERR_CANT_SHOW_NETTAB_INETCFG, NULL ); SetWindowLong( hwnd, DWLP_MSGRESULT, -1 ); return TRUE; } break; } break; } } return FALSE; } void NeEnsureNetshellLoaded ( IN PEINFO* pInfo) { // Load the netshell utilities interface. The interface is freed in PeTerm. // if (!pInfo->pNetConUtilities) { // Initialize the NetConnectionsUiUtilities // HRESULT hr = HrCreateNetConnectionUtilities(&pInfo->pNetConUtilities); } } BOOL NeInit( 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; pInfo = PeContext( hwndPage ); if (!pInfo) { return TRUE; } // Initialize page-specific context information. // pInfo->hwndLbServerType = GetDlgItem( hwndPage, CID_NE_LB_ServerType ); ASSERT( pInfo->hwndLbServerType ); pInfo->hwndPbSettings = GetDlgItem( hwndPage, CID_NE_PB_Settings ); ASSERT( pInfo->hwndPbSettings ); pInfo->hwndLvComponents = GetDlgItem( hwndPage, CID_NE_LV_Components ); ASSERT( pInfo->hwndLvComponents ); pInfo->hwndPbAdd = GetDlgItem( hwndPage, CID_NE_PB_Add ); ASSERT( pInfo->hwndPbAdd ); pInfo->hwndPbRemove = GetDlgItem( hwndPage, CID_NE_PB_Remove ); ASSERT( pInfo->hwndPbRemove ); pInfo->hwndPbProperties = GetDlgItem( hwndPage, CID_NE_PB_Properties ); ASSERT( pInfo->hwndPbProperties ); pInfo->hwndDescription = GetDlgItem( hwndPage, CID_NE_LB_ComponentDesc ); ASSERT( pInfo->hwndDescription ); // Initialize page. // pEntry = pInfo->pArgs->pEntry; // Initialize the server type combo box with the strings and the selection. // if (pEntry->dwType == RASET_Vpn) { INT i; LBTABLEITEM* pItem; // Whistler bug 312921 CM/RAS should default to PPTP instead of L2TP // LBTABLEITEM aItems[] = { SID_ST_VpnAuto, VS_PptpFirst, SID_ST_VpnPptp, VS_PptpOnly, SID_ST_VpnL2tp, VS_L2tpOnly, 0, 0 }; for (pItem = aItems; pItem->sidItem != 0; ++pItem) { i = ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbServerType, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData)); if (pItem->dwData == pEntry->dwVpnStrategy) { ComboBox_SetCurSel( pInfo->hwndLbServerType, i ); } } // If nothing was selected, then the strategy must have been one of the // VS_xxxxFirst values. Set the current selection to automatic. if ( ComboBox_GetCurSel ( pInfo->hwndLbServerType ) < 0 ) ComboBox_SetCurSel( pInfo->hwndLbServerType, 0 ); // Change the label to be VPN-specific per bug 307526. // { TCHAR* psz; psz = PszFromId( g_hinstDll, SID_NE_VpnServerLabel ); if (psz) { SetWindowText( GetDlgItem( hwndPage, CID_NE_ST_ServerType ), psz ); Free( psz ); } } } else if (pEntry->dwType == RASET_Broadband) { INT i; LBTABLEITEM* pItem; LBTABLEITEM aItems[] = { SID_ST_BbPppoe, BP_Ppp, 0, 0 }; for (pItem = aItems; pItem->sidItem != 0; ++pItem) { i = ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbServerType, pItem->sidItem, (VOID* )UlongToPtr(pItem->dwData)); } ComboBox_SetCurSel( pInfo->hwndLbServerType, 0 ); // Change the label to be broadband-specific // { TCHAR* psz; psz = PszFromId( g_hinstDll, SID_NE_BbServerLabel ); if (psz) { SetWindowText( GetDlgItem( hwndPage, CID_NE_ST_ServerType ), psz ); Free( psz ); } } } else { ComboBox_AddItemFromId (g_hinstDll, pInfo->hwndLbServerType, SID_ST_Ppp, (VOID*)BP_Ppp ); if (!pInfo->pArgs->fRouter) { ComboBox_AddItemFromId (g_hinstDll, pInfo->hwndLbServerType, SID_ST_Slip, (VOID*)BP_Slip ); } if (pEntry->dwBaseProtocol == BP_Ppp) { ComboBox_SetCurSel(pInfo->hwndLbServerType, 0 ); } else { ComboBox_SetCurSel( pInfo->hwndLbServerType, 1 ); EnableWindow( pInfo->hwndPbSettings, FALSE ); } } // Set the image list for the state of the check boxes. // ListView_InstallChecks( pInfo->hwndLvComponents, g_hinstDll ); ListView_InsertSingleAutoWidthColumn( pInfo->hwndLvComponents ); // Set the image list for the component bitmaps. Unfortunately we have to // duplicate it (as opposed to share) because the image list for the state // icons is not shared. (If we set the shared style, all image lists would // have to be deleted manually. // { ZeroMemory (&pInfo->cild, sizeof(pInfo->cild)); pInfo->cild.cbSize = sizeof(pInfo->cild); if (SetupDiGetClassImageList (&pInfo->cild)) { HIMAGELIST himlSmall = ImageList_Duplicate (pInfo->cild.ImageList); ListView_SetImageList (pInfo->hwndLvComponents, himlSmall, LVSIL_SMALL); } } // Get the interface used to change network configuration and lock it. // The description of who has the lock (us) comes from the title of our // parent dialog. This is done so that when other applications try to obtain // the lock (and fail) they get an indication of who has it locked. They // can then direct the user to close our window to release the lock. // { BOOL fEnableAdd = TRUE; HRESULT hr; TCHAR pszParentCaption [MAX_PATH] = {0}; GetWindowText (GetParent(hwndPage), pszParentCaption, MAX_PATH); pInfo->fInitCom = TRUE; hr = HrCreateAndInitializeINetCfg (&pInfo->fInitCom, &pInfo->pNetCfg, TRUE, 0, pszParentCaption, NULL); if (S_OK == hr) { // Refresh the list view. // hr = HrNeRefreshListView (pInfo); // Reset the state of the buttons as if something changed. // NeLvItemChanged (pInfo); pInfo->fNetCfgLock = TRUE; } else { DWORD dwMsg = SID_NE_ReadOnly; //For whistler bug 311566 // if (NETCFG_E_NO_WRITE_LOCK == hr) { pInfo->fReadOnly = TRUE; } if (NETCFG_E_NEED_REBOOT == hr) { dwMsg = SID_NE_Reboot; } else if (E_ACCESSDENIED == hr) { pInfo->fNonAdmin = TRUE; dwMsg = SID_NE_AccessDenied; } // Uh.. ok let's try that again in read-only mode hr = HrCreateAndInitializeINetCfg (&pInfo->fInitCom, &pInfo->pNetCfg,FALSE, 0, pszParentCaption, NULL); if (S_OK == hr) { // Refresh the list view. // hr = HrNeRefreshListView (pInfo); // Reset the state of the buttons as if something changed. // NeLvItemChanged (pInfo); MsgDlg( pInfo->hwndDlg, dwMsg, NULL ); } } // Get the interface so we can check our access rights to the UI // NeEnsureNetshellLoaded (pInfo); if (NULL != pInfo->pNetConUtilities) { fEnableAdd = INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_AddRemoveComponents); } // Disable some buttons if user does not have privilege // if (pInfo->fReadOnly || (NULL == pInfo->pNetConUtilities)) { EnableWindow(pInfo->hwndPbAdd, FALSE); EnableWindow(pInfo->hwndPbRemove, FALSE); EnableWindow(pInfo->hwndPbProperties, FALSE); } // Disable some buttons if running in non-admin mode else if (pInfo->fNonAdmin) { EnableWindow(pInfo->hwndPbAdd, FALSE); EnableWindow(pInfo->hwndPbRemove, FALSE); } else { EnableWindow(pInfo->hwndPbAdd, fEnableAdd); // Other buttons enabled via NeLvItemChanged } // pmay: 348623 // // Hide some buttons if we're remote admining // if (pInfo->pArgs->fRemote) { ShowWindow(pInfo->hwndPbAdd, SW_HIDE); ShowWindow(pInfo->hwndPbRemove, SW_HIDE); } } return TRUE; } void NeServerTypeSelChange ( IN PEINFO* pInfo) { PBENTRY* pEntry; int iSel; DWORD dwValue; pEntry = pInfo->pArgs->pEntry; iSel = ComboBox_GetCurSel (pInfo->hwndLbServerType); ASSERT (CB_ERR != iSel); dwValue = (DWORD) ComboBox_GetItemData (pInfo->hwndLbServerType, iSel); // Regular connections choose between slip and ppp // if (pEntry->dwType != RASET_Vpn) { pEntry->dwBaseProtocol = dwValue; // When SLIP is selected, turn off all protocols but IP and indicate // the SLIP security page informational popup should appear. // if (BP_Slip == dwValue) { // No need to exclude the protocols. We lose this config state if // we remove this and its of no use anyway. PPP won't be done // if slip is selected -- [raos]. // // pEntry->dwfExcludedProtocols = ~NP_Ip; pInfo->fShowSlipPopup = TRUE; } HrNeRefreshListView (pInfo); } // Vpn connections select a strategy. When automatic is selected, // we need to make sure the authentication and encryption is // compatible // else { pEntry->dwVpnStrategy = dwValue; // Whistler bug 312921 CM/RAS should default to PPTP instead of L2TP // if (dwValue == VS_PptpFirst) { pEntry->dwDataEncryption = DE_Require; if( !(pEntry->dwAuthRestrictions & AR_F_AuthEAP ) ) { pEntry->dwAuthRestrictions = AR_F_TypicalSecure; } pEntry->dwTypicalAuth = TA_Secure; } } EnableWindow (pInfo->hwndPbSettings, !!(BP_Ppp == pEntry->dwBaseProtocol)); } BOOL NeRequestReboot ( IN PEINFO* pInfo) { NeEnsureNetshellLoaded (pInfo); if (pInfo->pNetConUtilities) { HRESULT hr; // A reboot is required. Ask the user if it is ok to reboot now // //$TODO NULL caption? hr = INetConnectionUiUtilities_QueryUserForReboot( pInfo->pNetConUtilities, pInfo->hwndDlg, NULL, QUFR_PROMPT); if (S_OK == hr) { // User requested a reboot, note this for processing in OnApply // which is triggered by the message posted below // pInfo->fRebootAlreadyRequested = TRUE; // Press the cancel button (changes have already been applied) // so the appropriate cleanup occurs. // PostMessage(pInfo->hwndDlg, PSM_PRESSBUTTON, (WPARAM)PSBTN_OK, 0); } else if (S_FALSE == hr) { // User denied to request to reboot // return FALSE; } } return TRUE; } void NeSaveBindingChanges(IN PEINFO* pInfo) { // Won't have changes to keep unless we have a writable INetCfg if (pInfo->pNetCfg) { int iItem; INetCfgComponent* pComponent; BOOL fEnabled; HRESULT hr; // Update the phone book entry with the enabled state of the components. // Do this by enumerating the components from the list view item data // and consulting the check state for each. // iItem = -1; while (-1 != (iItem = ListView_GetNextItem (pInfo->hwndLvComponents, iItem, LVNI_ALL))) { pComponent = PComponentFromItemIndex (pInfo->hwndLvComponents, iItem); ASSERT (pComponent); fEnabled = ListView_GetCheck (pInfo->hwndLvComponents, iItem); if(pComponent) { NeEnableComponent (pInfo, pComponent, fEnabled); } } } } void NeAddComponent ( IN PEINFO* pInfo) { NeEnsureNetshellLoaded (pInfo); // If we have our pointer to the interface used to bring up the add // component dialog (obtained above only once), call it. // if (pInfo->pNetConUtilities) { HRESULT hr; // We want to filter out protocols that RAS does not care about // We do this by sending in a CI_FILTER_INFO structure indicating // we want non-RAS protocols filtered out // CI_FILTER_INFO cfi = {0}; cfi.eFilter = FC_RASCLI; ASSERT (pInfo->pNetCfg); hr = INetConnectionUiUtilities_DisplayAddComponentDialog( pInfo->pNetConUtilities, pInfo->hwndDlg, pInfo->pNetCfg, &cfi); // If the user didn't cancel, refresh the list view. // if (S_FALSE != hr) { if (SUCCEEDED(hr)) { // Change the Cancel Button to CLOSE (because we committed changes) // PropSheet_CancelToClose(pInfo->hwndDlg); } // commit binding changes made (Raid #297216) NeSaveBindingChanges(pInfo); HrNeRefreshListView (pInfo); // Reset the state of the buttons as if something changed. // NeLvItemChanged (pInfo); // If reboot is needed request approval for this from the user // if (NETCFG_S_REBOOT == hr) { NeRequestReboot (pInfo); } } } } void NeRemoveComponent ( IN PEINFO* pInfo) { NeEnsureNetshellLoaded (pInfo); // If we have our pointer to the function used to bring up the remove // component dialog (obtained above only once), call it. // if (pInfo->pNetConUtilities) { HRESULT hr; INetCfgComponent* pComponent; pComponent = PComponentFromCurSel (pInfo->hwndLvComponents, NULL); ASSERT (pComponent); ASSERT (pInfo->pNetCfg); hr = INetConnectionUiUtilities_QueryUserAndRemoveComponent( pInfo->pNetConUtilities, pInfo->hwndDlg, pInfo->pNetCfg, pComponent); // If the user didn't cancel, refresh the list view. // if (S_FALSE != hr) { if (SUCCEEDED(hr)) { // Change the Cancel Button to CLOSE (because we committed changes) // PropSheet_CancelToClose(pInfo->hwndDlg); } NeSaveBindingChanges(pInfo); HrNeRefreshListView(pInfo); // Reset the state of the buttons as if something changed. // NeLvItemChanged (pInfo); // If reboot is needed request approval for this from the user // if (NETCFG_S_REBOOT == hr) { NeRequestReboot (pInfo); } } } } void NeLvClick ( IN PEINFO* pInfo, IN BOOL fDoubleClick) { //Add the IsWindowEnabled for whistler bug #204976 //Not to pop up the property dialog box if it is a router //and the selected List View item is IPX // if (fDoubleClick && IsWindowEnabled(pInfo->hwndPbProperties)) { INetCfgComponent* pComponent; int iItem; pComponent = PComponentFromCurSel (pInfo->hwndLvComponents, &iItem); if (pComponent) { HRESULT hr; if ( ListView_GetCheck (pInfo->hwndLvComponents, iItem)) { // Check if the component has property UI // // Create the UI info callback object if we haven't done so yet. // If this fails, we can still show properties. TCP/IP just might // not know which UI-variant to show. // if (!pInfo->punkUiInfoCallback) { HrCreateUiInfoCallbackObject (pInfo, &pInfo->punkUiInfoCallback); } // Check if the component has property UI hr = INetCfgComponent_RaisePropertyUi ( pComponent, pInfo->hwndDlg, NCRP_QUERY_PROPERTY_UI, pInfo->punkUiInfoCallback); if (S_OK == hr) { NeEnsureNetshellLoaded (pInfo); if ((NULL != pInfo->pNetConUtilities) && INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_RasChangeProperties)) { NeShowComponentProperties (pInfo); } } } } } } void NeLvItemChanged ( IN PEINFO* pInfo) { LPWSTR pszwDescription = NULL; BOOL fEnableRemove = FALSE; BOOL fEnableProperties = FALSE; INetCfgComponent* pComponent; int iItem; // Get the current selection if it exists. // pComponent = PComponentFromCurSel (pInfo->hwndLvComponents, &iItem); if (pComponent) { NeEnsureNetshellLoaded (pInfo); // Determine if removal is allowed // if (NULL != pInfo->pNetConUtilities) { DWORD dwFlags = 0; HRESULT hr; fEnableRemove = INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_AddRemoveComponents); //Now disable the user ability to uninstall TCP stack //for whistler bug 322846 gangz // hr = INetCfgComponent_GetCharacteristics(pComponent, &dwFlags ); if( SUCCEEDED(hr) && (NCF_NOT_USER_REMOVABLE & dwFlags) ) { fEnableRemove = FALSE; } } // See if the properties UI should be allowed. Only allow it for // enabled items that have UI to display. // { HRESULT hr = S_OK; if (ListView_GetCheck (pInfo->hwndLvComponents, iItem)) { // Check if the component has property UI // INetCfgComponent* pComponentTmp = PComponentFromCurSel (pInfo->hwndLvComponents, NULL); ASSERT (pComponentTmp); // Create the UI info callback object if we haven't done so yet. // If this fails, we can still show properties. TCP/IP just might // not know which UI-variant to show. // if (!pInfo->punkUiInfoCallback) { HrCreateUiInfoCallbackObject (pInfo, &pInfo->punkUiInfoCallback); } if(pComponentTmp) { // Check if the component has property UI hr = INetCfgComponent_RaisePropertyUi ( pComponentTmp, pInfo->hwndDlg, NCRP_QUERY_PROPERTY_UI, pInfo->punkUiInfoCallback); if ((S_OK == hr) && (NULL != pInfo->pNetConUtilities)) { fEnableProperties = INetConnectionUiUtilities_UserHasPermission( pInfo->pNetConUtilities, NCPERM_RasChangeProperties); } } } } // Bug #221837 (danielwe): Set member vars based on whether they // are checked in the UI // { PBENTRY * pEntry; BOOL fIsChecked; LPWSTR pszwId = NULL; pEntry = pInfo->pArgs->pEntry; fIsChecked = ListView_GetCheck(pInfo->hwndLvComponents, iItem); if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId))) { // For whistler 522872 // if( CSTR_EQUAL == CompareStringW( LOCALE_INVARIANT, NORM_IGNORECASE, NETCFG_CLIENT_CID_MS_MSClient, -1, pszwId, -1 ) ) { pEntry->fBindMsNetClient = fIsChecked; } else if( CSTR_EQUAL == CompareStringW( LOCALE_INVARIANT, NORM_IGNORECASE, NETCFG_SERVICE_CID_MS_SERVER, -1, pszwId, -1 ) ) { pEntry->fShareMsFilePrint = fIsChecked; } // pmay 406630 // // Disable the properties of all components but tcpip if we // are running in non-admin mode // else if ( CSTR_EQUAL == CompareStringW( LOCALE_INVARIANT, NORM_IGNORECASE, NETCFG_TRANS_CID_MS_TCPIP, -1, pszwId, -1) ) { if (pInfo->fNonAdmin) { fEnableProperties = FALSE; } } CoTaskMemFree(pszwId); } } // Bug #348623 (pmay): // // Ipx is hardcoded to disable properties when remote admining // a router. // if (pInfo->pArgs->fRouter ) //commented for bug #204976 //&& pInfo->pArgs->fRemote) { LPWSTR pszwId = NULL; if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId))) { if ( CSTR_EQUAL== CompareStringW( LOCALE_INVARIANT, NORM_IGNORECASE, NETCFG_TRANS_CID_MS_NWIPX, -1, pszwId, -1) ) { fEnableProperties = FALSE; } CoTaskMemFree(pszwId); } } // Get the description text. Failure is okay here. It just means // we'll display nothing. // INetCfgComponent_GetHelpText (pComponent, &pszwDescription); } // Update the UI with its new state. // if (!pInfo->fReadOnly) { EnableWindow (pInfo->hwndPbRemove, fEnableRemove); EnableWindow (pInfo->hwndPbProperties, fEnableProperties); } if(NULL != pszwDescription) { SetWindowText (pInfo->hwndDescription, pszwDescription); CoTaskMemFree (pszwDescription); } } void NeLvDeleteItem ( IN PEINFO* pInfo, IN NM_LISTVIEW* pnmlv) { // Release our component object stored as the lParam of the list view // item. // INetCfgComponent* pComponent; pComponent = PComponentFromItemIndex (pInfo->hwndLvComponents, pnmlv->iItem); ReleaseObj (pComponent); } //---------------------------------------------------------------------------- // Networking property page PPP Settings dialog //---------------------------------------------------------------------------- INT_PTR CALLBACK PpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) { PEINFO* pInfo; PBENTRY* pEntry; switch (unMsg) { case WM_INITDIALOG: { pInfo = (PEINFO*)lparam; ASSERT (pInfo); pEntry = pInfo->pArgs->pEntry; CheckDlgButton (hwnd, CID_NE_EnableLcp, (pEntry->fLcpExtensions) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton (hwnd, CID_NE_EnableCompression, (pEntry->fSwCompression) ? BST_CHECKED : BST_UNCHECKED); //Cut Negotiate multi-link for whistler bug 385842 // CheckDlgButton (hwnd, CID_NE_NegotiateMultilinkAlways, (pEntry->fNegotiateMultilinkAlways) ? BST_CHECKED : BST_UNCHECKED); SetWindowLongPtr (hwnd, DWLP_USER, (ULONG_PTR )lparam); // Center dialog on the owner window. // CenterWindow(hwnd, GetParent(hwnd)); // Add context help button to title bar. // AddContextHelpButton(hwnd); return TRUE; } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwPpHelp, hwnd, unMsg, wparam, lparam ); break; } case WM_COMMAND: { if ((IDOK == LOWORD(wparam)) && (BN_CLICKED == HIWORD(wparam))) { pInfo = (PEINFO*)GetWindowLongPtr (hwnd, DWLP_USER); ASSERT (pInfo); pEntry = pInfo->pArgs->pEntry; pEntry->fLcpExtensions = (BST_CHECKED == IsDlgButtonChecked (hwnd, CID_NE_EnableLcp)); pEntry->fSwCompression = (BST_CHECKED == IsDlgButtonChecked (hwnd, CID_NE_EnableCompression)); //Cut Negotiate multi-link for whistler bug 385842 // pEntry->fNegotiateMultilinkAlways = (BST_CHECKED == IsDlgButtonChecked (hwnd, CID_NE_NegotiateMultilinkAlways)); /* pEntry->fNegotiateMultilinkAlways = FALSE; */ EndDialog (hwnd, TRUE); return TRUE; } else if ((IDCANCEL == LOWORD(wparam)) && (BN_CLICKED == HIWORD(wparam))) { EndDialog (hwnd, FALSE); return TRUE; } break; } } return FALSE; } INT_PTR CALLBACK SaUnavailDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) // DialogProc callback for the Shared Access Unavailable page of the Entry property // sheet. // Parameters and return value are as described for standard windows // 'DialogProc's. // { #if 0 TRACE4( "SaUnavailDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif switch (unMsg) { case WM_INITDIALOG: { LPWSTR pszError; PEINFO* pInfo = PeContext( hwnd ); ASSERT(pInfo); if (pInfo == NULL) { break; } pszError = PszFromId(g_hinstDll, pInfo->pArgs->hShowHNetPagesResult == HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED) ? SID_SA_NoWMIError : SID_SA_StoreError); if(NULL != pszError) { SetDlgItemText(hwnd, CID_SA_ST_ErrorText, pszError); Free(pszError); } } case WM_HELP: case WM_CONTEXTMENU: { // ContextHelp( g_adwSaHelp, hwnd, unMsg, wparam, lparam ); break; } } return FALSE; } //---------------------------------------------------------------------------- // Routing property page (PLACEHOLDER only) // 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 Routing page of the Entry property sheet. // Parameters and return value are as described for standard windows // 'DialogProc's. // { return FALSE; } /*---------------------------------------------------------------------------- ** (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_PTR nStatus; TRACE("RouterCallbackDlg"); nStatus = 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 (nStatus) ? TRUE : FALSE; } 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: ContextHelp( g_adwCrHelp, hwnd, unMsg, wparam, lparam ); 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. */ { TRACE3("CrCommand(n=%d,i=%d,c=$%x)", (DWORD)wNotification,(DWORD)wId,(ULONG_PTR )hwndCtrl); 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, (ULONG_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 ) ); // Add context help button to title bar. // AddContextHelpButton( 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; pInfo->pArgs->pUser->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"); // pmay: 213060 // // Cleanup the numbers // if ( pInfo->hwndLvNumbers ) { CbutilLvNumbersCleanup( pInfo->hwndLvNumbers ); } 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 ); } INT_PTR CALLBACK SaDisableFirewallWarningDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) { switch(unMsg) { case WM_COMMAND: { switch(LOWORD(wparam)) { case IDYES: case IDNO: if(BST_CHECKED == IsDlgButtonChecked(hwnd, CID_SA_PB_DisableFirewallWarning)) { HKEY hFirewallKey; if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, g_pszFirewallRegKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hFirewallKey, NULL)) { DWORD dwValue = TRUE; RegSetValueEx(hFirewallKey, g_pszDisableFirewallWarningValue, 0, REG_DWORD, (CONST BYTE*)&dwValue, sizeof(dwValue)); RegCloseKey(hFirewallKey); } } // fallthru case IDCANCEL: EndDialog(hwnd, LOWORD(wparam)); break; } break; } } return FALSE; } BOOL SaIsAdapterDHCPEnabled(IHNetConnection* pConnection) { HRESULT hr; BOOL fDHCP = FALSE; GUID* pAdapterGuid; hr = IHNetConnection_GetGuid(pConnection, &pAdapterGuid); if(SUCCEEDED(hr)) { LPOLESTR pAdapterName; hr = StringFromCLSID(pAdapterGuid, &pAdapterName); if(SUCCEEDED(hr)) { SIZE_T Length = wcslen(pAdapterName); LPSTR pszAnsiAdapterName = Malloc(Length + 1); if(NULL != pszAnsiAdapterName) { if(0 != WideCharToMultiByte(CP_ACP, 0, pAdapterName, (int)(Length + 1), pszAnsiAdapterName, (int)(Length + 1), NULL, NULL)) { HMODULE hIpHelper; hIpHelper = LoadLibrary(L"iphlpapi"); if(NULL != hIpHelper) { DWORD (WINAPI *pGetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG); pGetAdaptersInfo = (DWORD (WINAPI*)(PIP_ADAPTER_INFO, PULONG)) GetProcAddress(hIpHelper, "GetAdaptersInfo"); if(NULL != pGetAdaptersInfo) { ULONG ulSize = 0; if(ERROR_BUFFER_OVERFLOW == pGetAdaptersInfo(NULL, &ulSize)) { PIP_ADAPTER_INFO pInfo = Malloc(ulSize); if(NULL != pInfo) { if(ERROR_SUCCESS == pGetAdaptersInfo(pInfo, &ulSize)) { PIP_ADAPTER_INFO pAdapterInfo = pInfo; do { if(0 == lstrcmpA(pszAnsiAdapterName, pAdapterInfo->AdapterName)) { fDHCP = !!pAdapterInfo->DhcpEnabled; break; } } while(NULL != (pAdapterInfo = pAdapterInfo->Next)); } Free(pInfo); } } } FreeLibrary(hIpHelper); } } Free(pszAnsiAdapterName); } CoTaskMemFree(pAdapterName); } CoTaskMemFree(pAdapterGuid); } return fDHCP; }