/* Copyright (c) 1995, Microsoft Corporation, all rights reserved ** ** pref.c ** Remote Access Common Dialog APIs ** User Preferences property sheet ** ** 08/22/95 Steve Cobb */ #include "rasdlgp.h" #include // FileOpen dialog /* Page definitions. */ //#define UP_AdPage 0 //#define UP_CbPage 1 //#define UP_GpPage 2 //#define UP_PlPage 3 #define UP_PageCount 2 // // Defines flags the modify the behavior of the user preferences // dialog // #define UP_F_AutodialMode 0x1 // Come up with focus on autodial page /*---------------------------------------------------------------------------- ** Help maps **---------------------------------------------------------------------------- */ static DWORD g_adwAdHelp[] = { CID_AD_ST_Enable, HID_AD_LV_Enable, CID_AD_LV_Enable, HID_AD_LV_Enable, CID_AD_ST_Attempts, HID_AD_EB_Attempts, CID_AD_EB_Attempts, HID_AD_EB_Attempts, CID_AD_ST_Seconds, HID_AD_EB_Seconds, CID_AD_EB_Seconds, HID_AD_EB_Seconds, CID_AD_ST_Idle, HID_AD_EB_Idle, CID_AD_EB_Idle, HID_AD_EB_Idle, CID_AD_CB_AskBeforeAutodial, HID_AD_CB_AskBeforeAutodial, CID_AD_CB_AskBeforeAutodial, HID_AD_CB_AskBeforeAutodial, CID_AD_CB_DisableThisSession, HID_AD_CB_DisableThisSession, 0, 0 }; static DWORD g_adwCbHelp[] = { CID_CB_RB_No, HID_CB_RB_No, CID_CB_RB_Maybe, HID_CB_RB_Maybe, CID_CB_RB_Yes, HID_CB_RB_Yes, CID_CB_LV_Numbers, HID_CB_LV_Numbers, CID_CB_PB_Edit, HID_CB_PB_Edit, CID_CB_PB_Delete, HID_CB_PB_Delete, 0, 0 }; static DWORD g_adwGpHelp[] = { CID_GP_CB_Preview, HID_GP_CB_Preview, CID_GP_CB_Location, HID_GP_CB_Location, CID_GP_CB_Lights, HID_GP_CB_Lights, CID_GP_CB_Progress, HID_GP_CB_Progress, CID_GP_CB_CloseOnDial, HID_GP_CB_CloseOnDial, CID_GP_CB_UseWizard, HID_GP_CB_UseWizard, CID_GP_CB_AutodialPrompt, HID_GP_CB_AutodialPrompt, CID_GP_CB_PhonebookEdits, HID_GP_CB_PhonebookEdits, CID_GP_CB_LocationEdits, HID_GP_CB_LocationEdits, 0, 0 }; static DWORD g_adwCoHelp[] = { CID_CO_GB_LogonPrivileges, HID_CO_GB_LogonPrivileges, CID_CO_ST_AllowConnectionModification, HID_CO_CB_AllowConnectionModification, CID_CO_CB_AllowConnectionModification, HID_CO_CB_AllowConnectionModification, 0, 0 }; static DWORD g_adwPlHelp[] = { CID_PL_ST_Open, HID_PL_ST_Open, CID_PL_RB_SystemList, HID_PL_RB_SystemList, CID_PL_RB_PersonalList, HID_PL_RB_PersonalList, CID_PL_RB_AlternateList, HID_PL_RB_AlternateList, CID_PL_CL_Lists, HID_PL_CL_Lists, CID_PL_PB_Browse, HID_PL_PB_Browse, 0, 0 }; /*---------------------------------------------------------------------------- ** Local datatypes (alphabetically) **---------------------------------------------------------------------------- */ /* User Preferences property sheet argument block. */ #define UPARGS struct tagUPARGS UPARGS { /* Caller's arguments to the stub API. */ HLINEAPP hlineapp; BOOL fNoUser; BOOL fIsUserAdmin; PBUSER* pUser; PBFILE** ppFile; /* Stub API return value. */ BOOL fResult; /* Flags that provide more info see UP_F_* values */ DWORD dwFlags; }; /* User Preferences property sheet context block. All property pages refer to ** the single context block associated with the sheet. */ #define UPINFO struct tagUPINFO UPINFO { /* Stub API arguments from UpPropertySheet. */ UPARGS* pArgs; /* TAPI session handle. Should always be addressed thru the pointer since ** the handle passed down from caller, if any, will be used instead of ** 'hlineapp'. */ HLINEAPP hlineapp; HLINEAPP* pHlineapp; /* Property sheet dialog and property page handles. 'hwndFirstPage' is ** the handle of the first property page initialized. This is the page ** that allocates and frees the context block. */ HWND hwndDlg; HWND hwndFirstPage; HWND hwndCo; HWND hwndGp; HWND hwndAd; HWND hwndCb; HWND hwndPl; /* Auto-dial page. */ HWND hwndLvEnable; HWND hwndEbAttempts; HWND hwndEbSeconds; HWND hwndEbIdle; BOOL fChecksInstalled; /* Callback page. */ HWND hwndRbNo; HWND hwndRbMaybe; HWND hwndRbYes; HWND hwndLvNumbers; HWND hwndPbEdit; HWND hwndPbDelete; /* Phone list page. */ HWND hwndRbSystem; HWND hwndRbPersonal; HWND hwndRbAlternate; HWND hwndClbAlternates; HWND hwndPbBrowse; /* Working data read from and written to registry with phonebook library. */ PBUSER user; // Current user PBUSER userLogon; // Logon preferences }; /*---------------------------------------------------------------------------- ** Local prototypes (alphabetically) **---------------------------------------------------------------------------- */ VOID AdApply( IN UPINFO* pInfo ); INT_PTR CALLBACK AdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL AdFillLvEnable( IN UPINFO* pInfo ); BOOL AdInit( IN HWND hwndPage, IN OUT UPARGS* pArgs ); LVXDRAWINFO* AdLvEnableCallback( IN HWND hwndLv, IN DWORD dwItem ); VOID CbApply( IN UPINFO* pInfo ); BOOL CbCommand( IN UPINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK CbDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL CbInit( IN HWND hwndPage ); VOID CbUpdateLvAndPbState( IN UPINFO* pInfo ); BOOL CoApply( IN UPINFO* pInfo ); INT_PTR CALLBACK CoDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL CoInit( IN HWND hwndPage, IN OUT UPARGS* pArgs ); VOID GpApply( IN UPINFO* pInfo ); BOOL GpCommand( IN UPINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK GpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL GpInit( IN HWND hwndPage ); VOID GpUpdateCbStates( IN UPINFO* pInfo ); BOOL PlApply( IN UPINFO* pInfo ); VOID PlBrowse( IN UPINFO* pInfo ); BOOL PlCommand( IN UPINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl ); INT_PTR CALLBACK PlDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ); BOOL PlInit( IN HWND hwndPage ); BOOL UpApply( IN HWND hwndPage ); VOID UpCancel( IN HWND hwndPage ); UPINFO* UpContext( IN HWND hwndPage ); VOID UpExit( IN UPINFO* pInfo ); VOID UpExitInit( IN HWND hwndDlg ); UPINFO* UpInit( IN HWND hwndFirstPage, IN UPARGS* pArgs ); VOID UpTerm( IN HWND hwndPage ); /*---------------------------------------------------------------------------- ** User Preferences property sheet entry point **---------------------------------------------------------------------------- */ BOOL UserPreferencesDlg( IN HLINEAPP hlineapp, IN HWND hwndOwner, IN BOOL fNoUser, IN DWORD dwFlags, OUT PBUSER* pUser, OUT PBFILE** ppFile ) /* Pops up the User Preferences property sheet, reading and storing the ** result in the USER registry. 'HwndOwner' is the handle of the owning ** window. 'FNoUser' indicates logon preferences, rather than user ** preferences should be edited. 'Hlineapp' is an open TAPI session ** handle or NULL if none. 'Puser' is caller's buffer to receive the ** result. 'PpFile' is address of caller's file block which is filled in, ** if user chooses to open a new phonebook file, with the information ** about the newly open file. It is caller's responsibility to ** ClosePhonebookFile and Free the returned block. ** ** Returns true if user pressed OK and settings were saved successfully, ** or false if user pressed Cancel or an error occurred. The routine ** handles the display of an appropriate error popup. */ { PROPSHEETHEADER header; PROPSHEETPAGE* apage; PROPSHEETPAGE* ppage; TCHAR* pszTitle; UPARGS args; BOOL bIsAdmin; DWORD dwPageCount, i; TRACE("UpPropertySheet"); // If the user doesn't have administrative priveleges, then // we don't allow the Connections tab to show. ZeroMemory(&args, sizeof(args)); args.fIsUserAdmin = FIsUserAdminOrPowerUser(); dwPageCount = UP_PageCount; // Initialize the array of pages apage = Malloc (dwPageCount * sizeof (PROPSHEETPAGE)); if (!apage) return FALSE; /* Initialize OUT parameter and property sheet argument block. */ ZeroMemory( pUser, sizeof(*pUser) ); args.pUser = pUser; args.fNoUser = fNoUser; args.ppFile = ppFile; args.hlineapp = hlineapp; args.fResult = FALSE; args.dwFlags = dwFlags; if (ppFile) *ppFile = NULL; pszTitle = PszFromId( g_hinstDll, (fNoUser) ? SID_UpLogonTitle : SID_UpTitle ); ZeroMemory( &header, sizeof(header) ); header.dwSize = sizeof(PROPSHEETHEADER); header.dwFlags = PSH_PROPSHEETPAGE + PSH_NOAPPLYNOW; header.hwndParent = hwndOwner; header.hInstance = g_hinstDll; header.pszCaption = (pszTitle) ? pszTitle : TEXT(""); header.nPages = dwPageCount; header.ppsp = apage; ZeroMemory( apage, dwPageCount * sizeof (PROPSHEETPAGE) ); i = 0; // Add the autodial page ppage = &apage[ i ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (fNoUser) ? MAKEINTRESOURCE( PID_AD_AutoDialLogon ) : MAKEINTRESOURCE( PID_AD_AutoDial ), ppage->pfnDlgProc = AdDlgProc; ppage->lParam = (LPARAM )&args; i++; ppage = &apage[ i ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = MAKEINTRESOURCE( PID_CB_CallbackSettings ); ppage->pfnDlgProc = CbDlgProc; i++; #if 0 ppage = &apage[ UP_GpPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (fNoUser) ? MAKEINTRESOURCE( PID_GP_GeneralPrefLogon ) : MAKEINTRESOURCE( PID_GP_GeneralPreferences ), ppage->pfnDlgProc = GpDlgProc; ppage = &apage[ UP_PlPage ]; ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = g_hinstDll; ppage->pszTemplate = (fNoUser) ? MAKEINTRESOURCE( PID_PL_PhoneListLogon ) : MAKEINTRESOURCE( PID_PL_PhoneList ), ppage->pfnDlgProc = PlDlgProc; #endif if (PropertySheet( &header ) == -1) { TRACE("PropertySheet failed"); ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); } Free0( pszTitle ); return args.fResult; } // Allows the editing of ras user preferences DWORD APIENTRY RasUserPrefsDlgInternal ( HWND hwndParent, DWORD dwFlags) { BOOL bCommit = FALSE; PBFILE * pPbFile = NULL; PBUSER pbuser; DWORD dwErr; // Load ras if neccessary dwErr = LoadRas( g_hinstDll, hwndParent ); if (dwErr != 0) { ErrorDlg( hwndParent, SID_OP_LoadRas, dwErr, NULL ); return dwErr; } // Launch the user preferences dialog bCommit = UserPreferencesDlg( 0, hwndParent, FALSE, dwFlags, &pbuser, &pPbFile ); // Commit any neccessary changes if (bCommit) { } return NO_ERROR; } DWORD APIENTRY RasUserPrefsDlgAutodial ( HWND hwndParent) { return RasUserPrefsDlgInternal(hwndParent, UP_F_AutodialMode); } DWORD APIENTRY RasUserPrefsDlg ( HWND hwndParent) { return RasUserPrefsDlgInternal(hwndParent, 0); } DWORD APIENTRY RasUserEnableManualDial ( IN HWND hwndParent, IN BOOL bLogon, IN BOOL bEnable ) /* Called when the "operator dial" menu item is checked. */ { return SetUserManualDialEnabling ( bEnable, (bLogon) ? UPM_Logon : UPM_Normal); } DWORD APIENTRY RasUserGetManualDial ( IN HWND hwndParent, // parent for error dialogs IN BOOL bLogon, // whether a user is logged in IN PBOOL pbEnabled ) // whether to enable or not /* Called when the "operator dial" menu item is checked. */ { return GetUserManualDialEnabling ( pbEnabled, (bLogon) ? UPM_Logon : UPM_Normal ); } /*---------------------------------------------------------------------------- ** User Preferences property sheet ** Listed alphabetically **---------------------------------------------------------------------------- */ BOOL UpApply( IN HWND hwndPage ) /* Saves the contents of the property sheet. 'hwndPage' is the property ** sheet page. Pops up any errors that occur. ** ** Returns false if invalid, true otherwise. */ { DWORD dwErr; UPINFO* pInfo; TRACE("UpApply"); pInfo = UpContext( hwndPage ); if (!pInfo) return TRUE; if ( pInfo->hwndAd ) AdApply( pInfo ); if (pInfo->hwndCb) CbApply( pInfo ); #if 0 if (pInfo->hwndGp) GpApply( pInfo ); #endif if (pInfo->hwndCo) CoApply ( pInfo ); #if 0 if (pInfo->hwndPl) { if (!PlApply( pInfo )) return FALSE; } #endif pInfo->user.fDirty = TRUE; // Save off the user preferences // dwErr = g_pSetUserPreferences( NULL, &pInfo->user, pInfo->pArgs->fNoUser ? UPM_Logon : UPM_Normal ); if (dwErr != 0) { if (*pInfo->pArgs->ppFile) { ClosePhonebookFile( *pInfo->pArgs->ppFile ); *pInfo->pArgs->ppFile = NULL; } ErrorDlg( pInfo->hwndDlg, SID_OP_WritePrefs, dwErr, NULL ); UpExit( pInfo ); return TRUE; } // Save off the logon preferences if we loaded them. // if (! pInfo->pArgs->fNoUser ) { dwErr = g_pSetUserPreferences( NULL, &pInfo->userLogon, UPM_Logon ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_WritePrefs, dwErr, NULL ); UpExit( pInfo ); return TRUE; } } CopyMemory( pInfo->pArgs->pUser, &pInfo->user, sizeof(PBUSER) ); pInfo->pArgs->fResult = TRUE; return TRUE; } VOID UpCancel( IN HWND hwndPage ) /* Cancel was pressed. 'HwndPage' is the handle of a property page. */ { TRACE("UpCancel"); } UPINFO* UpContext( IN HWND hwndPage ) /* Retrieve the property sheet context from a property page handle. */ { return (UPINFO* )GetProp( GetParent( hwndPage ), g_contextId ); } VOID UpExit( IN UPINFO* pInfo ) /* Forces an exit from the dialog. 'PInfo' is the property sheet context. ** ** Note: This cannot be called during initialization of the first page. ** See UpExitInit. */ { TRACE("UpExit"); PropSheet_PressButton( pInfo->hwndDlg, PSBTN_CANCEL ); } VOID UpExitInit( IN HWND hwndDlg ) /* Utility to report errors within UpInit and other first page ** initialization. 'HwndDlg' is the dialog window. */ { SetOffDesktop( hwndDlg, SOD_MoveOff, NULL ); SetOffDesktop( hwndDlg, SOD_Free, NULL ); PostMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( IDCANCEL , BN_CLICKED ), (LPARAM )GetDlgItem( hwndDlg, IDCANCEL ) ); } UPINFO* UpInit( IN HWND hwndFirstPage, IN UPARGS* pArgs ) /* Property sheet level initialization. 'HwndPage' is the handle of the ** first page. 'PArgs' is the API 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. */ { UPINFO* pInfo; DWORD dwErr; HWND hwndDlg; TRACE("UpInit"); hwndDlg = GetParent( hwndFirstPage ); ASSERT(hwndDlg); /* Allocate the context information block. */ pInfo = Malloc( sizeof(*pInfo) ); if (!pInfo) { ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); UpExitInit( hwndDlg ); return NULL; } /* Initialize the context block. */ ZeroMemory( pInfo, sizeof(*pInfo) ); pInfo->hwndDlg = hwndDlg; pInfo->pArgs = pArgs; pInfo->hwndFirstPage = hwndFirstPage; /* Read in the user preferences */ dwErr = g_pGetUserPreferences( NULL, &pInfo->user, pArgs->fNoUser ? UPM_Logon : UPM_Normal); if (dwErr != 0) { Free( pInfo ); ErrorDlg( hwndDlg, SID_OP_LoadPrefs, dwErr, NULL ); UpExitInit( hwndDlg ); return NULL; } /* If the fNoUser option was not selected, then load in the logon preferences separately, since we allow them to be modificed in this UI */ if (! pArgs->fNoUser ) { dwErr = g_pGetUserPreferences( NULL, &pInfo->userLogon, UPM_Logon); if (dwErr != 0) { Free( pInfo ); ErrorDlg( hwndDlg, SID_OP_LoadPrefs, dwErr, NULL ); UpExitInit( hwndDlg ); return NULL; } } /* Associate the context with the property sheet window. */ if (!SetProp( hwndDlg, g_contextId, pInfo )) { Free( pInfo ); ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); UpExitInit( hwndDlg ); return NULL; } /* Use caller's TAPI session handle, if any. */ if (pArgs->hlineapp) pInfo->pHlineapp = &pArgs->hlineapp; else pInfo->pHlineapp = &pInfo->hlineapp; TRACE("Context set"); /* Set even fixed tab widths, per spec. */ // SetEvenTabWidths( hwndDlg, UP_PageCount ); /* Position property sheet at standard offset from parent. { RECT rect; GetWindowRect( GetParent( hwndDlg ), &rect ); SetWindowPos( hwndDlg, NULL, rect.left + DXSHEET, rect.top + DYSHEET, 0, 0, SWP_NOZORDER + SWP_NOSIZE ); UnclipWindow( hwndDlg ); } */ CenterWindow ( hwndDlg, GetParent ( hwndDlg ) ); // // pmay: 292069 // // If the autodialer dialog has called into us, set focus to the // autodial tab. // if (pArgs->dwFlags & UP_F_AutodialMode) { PostMessage( hwndDlg, PSM_SETCURSELID, 0, (LPARAM)(INT)PID_AD_AutoDial); } return pInfo; } VOID UpTerm( IN HWND hwndPage ) /* Property sheet level termination. Releases the context block. ** 'HwndPage' is the handle of a property page. */ { UPINFO* pInfo; TRACE("UpTerm"); pInfo = UpContext( hwndPage ); // Only terminate for once by making sure that we // only terminate if this is the first page. if ( (pInfo) && (pInfo->hwndFirstPage == hwndPage) ) { // Cleanup the list view if ( pInfo->hwndLvNumbers ) { CbutilLvNumbersCleanup( pInfo->hwndLvNumbers ); } if (pInfo->fChecksInstalled) { ListView_UninstallChecks( pInfo->hwndLvEnable ); } if (pInfo->pHlineapp && *pInfo->pHlineapp != pInfo->pArgs->hlineapp) { TapiShutdown( *pInfo->pHlineapp ); } Free( pInfo ); TRACE("Context freed"); } RemoveProp( GetParent( hwndPage ), g_contextId ); } /*---------------------------------------------------------------------------- ** Auto Dial property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK AdDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Auto Dial page of the User Preferences ** property sheet. Parameters and return value are as described for ** standard windows 'DialogProc's. */ { #if 0 TRACE4("AdDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif if (ListView_OwnerHandler( hwnd, unMsg, wparam, lparam, AdLvEnableCallback )) { return TRUE; } switch (unMsg) { case WM_INITDIALOG: return AdInit( hwnd, (UPARGS* )(((PROPSHEETPAGE* )lparam)->lParam) ); case WM_HELP: case WM_CONTEXTMENU: ContextHelp( g_adwAdHelp, hwnd, unMsg, wparam, lparam ); break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case PSN_APPLY: { BOOL fValid; UPINFO* pInfo = UpContext ( hwnd ); TRACE("AdAPPLY"); // We have to apply if we are the first page... if (pInfo->hwndFirstPage == hwnd) { /* Call UpApply only on first page. */ fValid = UpApply( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, (fValid) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ); return TRUE; } } case PSN_RESET: { /* Call UpCancel only on first page. */ TRACE("AdRESET"); UpCancel( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, FALSE ); break; } } } break; case WM_DESTROY: { /* UpTerm will handle making sure it only does its ** thing once */ UpTerm( hwnd ); break; } } return FALSE; } VOID AdApply( IN UPINFO* pInfo ) /* Saves the contents of the property page. 'PInfo' is the property sheet ** context. */ { DWORD dwErr, dwFlag; UINT unValue; LV_ITEM item; INT i, iCount; BOOL f; TRACE("AdApply"); if (!pInfo->pArgs->fNoUser) { ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_PARAM + LVIF_STATE; iCount = ListView_GetItemCount( pInfo->hwndLvEnable ); for (i = 0; i < iCount; ++i) { BOOL fCheck; item.iItem = i; if (!ListView_GetItem( pInfo->hwndLvEnable, &item )) break; fCheck = ListView_GetCheck( pInfo->hwndLvEnable, i ); ASSERT(g_pRasSetAutodialEnable); dwErr = g_pRasSetAutodialEnable( (DWORD )item.lParam, fCheck ); if (dwErr != 0) ErrorDlg( pInfo->hwndDlg, SID_OP_SetADialInfo, dwErr, NULL ); } /* Set the autodial prompt information. * Flip it because the API wants true to mean "disable". */ dwFlag = (DWORD )!IsDlgButtonChecked( pInfo->hwndAd, CID_AD_CB_AskBeforeAutodial ); TRACE1("RasSetAutodialParam(%d)",dwFlag); dwErr = g_pRasSetAutodialParam( RASADP_DisableConnectionQuery, &dwFlag, sizeof(dwFlag) ); TRACE1("RasSetAutodialParam=%d",dwErr); // // pmay: 209762 // // Save the "disable current session" checkbox // dwFlag = (DWORD ) IsDlgButtonChecked(pInfo->hwndAd, CID_AD_CB_DisableThisSession ); dwErr = g_pRasSetAutodialParam( RASADP_LoginSessionDisable, &dwFlag, sizeof(dwFlag) ); } } BOOL AdFillLvEnable( IN UPINFO* pInfo ) /* Initialize the listview of checkboxes. 'PInfo' is the property sheet ** context. ** ** Note: This routine must only be called once. ** ** Returns true if focus is set, false otherwise. */ { DWORD dwErr; LOCATION* pLocations; DWORD cLocations; DWORD dwCurLocation; BOOL fFocusSet; fFocusSet = FALSE; ListView_DeleteAllItems( pInfo->hwndLvEnable ); /* Install "listview of check boxes" handling. */ pInfo->fChecksInstalled = ListView_InstallChecks( pInfo->hwndLvEnable, g_hinstDll ); if (!pInfo->fChecksInstalled) return FALSE; /* Insert an item for each location. */ pLocations = NULL; cLocations = 0; dwCurLocation = 0xFFFFFFFF; dwErr = GetLocationInfo( g_hinstDll, pInfo->pHlineapp, &pLocations, &cLocations, &dwCurLocation ); if (dwErr != 0) ErrorDlg( pInfo->hwndDlg, SID_OP_LoadTapiInfo, dwErr, NULL ); else { LV_ITEM item; LOCATION* pLocation; TCHAR* pszCurLoc; DWORD i; pszCurLoc = PszFromId( g_hinstDll, SID_IsCurLoc ); ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_PARAM; for (i = 0, pLocation = pLocations; i < cLocations; ++i, ++pLocation) { TCHAR* psz; TCHAR* pszText; DWORD cb; pszText = NULL; psz = StrDup( pLocation->pszName ); if (psz) { if (dwCurLocation == pLocation->dwId && pszCurLoc) { /* This is the current globally selected location. Append ** the " (the current location)" text. */ cb = lstrlen( psz ) + lstrlen(pszCurLoc) + 1; pszText = Malloc( cb * sizeof(TCHAR) ); if (pszText) { // Whistler bug 224074 use only lstrcpyn's to prevent // maliciousness // lstrcpyn( pszText, psz, cb ); lstrcat( pszText, pszCurLoc ); } Free( psz ); } else pszText = psz; } if (pszText) { BOOL fCheck; /* Get the initial check value for this location. */ ASSERT(g_pRasGetAutodialEnable); dwErr = g_pRasGetAutodialEnable( pLocation->dwId, &fCheck ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_GetADialInfo, dwErr, NULL ); fCheck = FALSE; } item.iItem = i; item.lParam = pLocation->dwId; item.pszText = pszText; ListView_InsertItem( pInfo->hwndLvEnable, &item ); ListView_SetCheck( pInfo->hwndLvEnable, i, fCheck ); if (dwCurLocation == pLocation->dwId) { /* Initial selection is the current location. */ ListView_SetItemState( pInfo->hwndLvEnable, i, LVIS_SELECTED + LVIS_FOCUSED, LVIS_SELECTED + LVIS_FOCUSED ); fFocusSet = TRUE; } Free( pszText ); } } Free0( pszCurLoc ); FreeLocationInfo( pLocations, cLocations ); /* 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->hwndLvEnable, 0, &col ); ListView_SetColumnWidth( pInfo->hwndLvEnable, 0, LVSCW_AUTOSIZE_USEHEADER ); } } return fFocusSet; } BOOL AdInit( IN HWND hwndPage, IN OUT UPARGS* 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. */ { UPINFO* pInfo; BOOL fFocusSet; HWND hwndUdAttempts; HWND hwndUdSeconds; HWND hwndUdIdle; DWORD dwErr; TRACE("AdInit"); /* We're first page, if the user isn't * an admin. */ pInfo = UpInit( hwndPage, pArgs ); if (!pInfo) return TRUE; // Make sure that a default location is created if there isn't one. bug // 168631 // dwErr = TapiNoLocationDlg( g_hinstDll, &(pInfo->pArgs->hlineapp), hwndPage ); if (dwErr != 0) { // Error here is treated as a "cancel" per bug 288385. // return TRUE; } /* Initialize page-specific context information. */ pInfo->hwndAd = hwndPage; if (!pArgs->fNoUser) { pInfo->hwndLvEnable = GetDlgItem( hwndPage, CID_AD_LV_Enable ); ASSERT(pInfo->hwndLvEnable); } if (!pArgs->fNoUser) { DWORD dwFlag, dwErr; DWORD cb; /* Initialize the listview. */ fFocusSet = AdFillLvEnable( pInfo ); /* Initialize autodial parameters. */ dwFlag = FALSE; cb = sizeof(dwFlag); TRACE("RasGetAutodialParam(DCQ)"); dwErr = g_pRasGetAutodialParam( RASADP_DisableConnectionQuery, &dwFlag, &cb ); TRACE1("RasGetAutodialParam=%d",dwErr); /* Flip it because the API wants true to mean "disable". */ CheckDlgButton( hwndPage, CID_AD_CB_AskBeforeAutodial, (BOOL )!dwFlag ); // // pmay: 209762 // // Initialize the "disable current session" checkbox // dwFlag = FALSE; cb = sizeof(dwFlag); dwErr = g_pRasGetAutodialParam( RASADP_LoginSessionDisable, &dwFlag, &cb ); CheckDlgButton( hwndPage, CID_AD_CB_DisableThisSession, (BOOL )dwFlag ); } return !fFocusSet; } LVXDRAWINFO* AdLvEnableCallback( 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. */ { /* The enhanced list view is used only to get the "wide selection bar" ** feature so our option list is not very interesting. ** ** Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'. */ static LVXDRAWINFO info = { 1, 0, 0, { 0 } }; return &info; } /*---------------------------------------------------------------------------- ** Callback property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK CbDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Callback page of the User Preferences ** property sheet. Parameters and return value are as described for ** standard windows 'DialogProc's. */ { #if 0 TRACE4("CbDlgProc(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 CbInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: ContextHelp( g_adwCbHelp, hwnd, unMsg, wparam, lparam ); break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case NM_DBLCLK: { UPINFO* pInfo = UpContext( hwnd ); ASSERT(pInfo); SendMessage( pInfo->hwndPbEdit, BM_CLICK, 0, 0 ); return TRUE; } case LVN_ITEMCHANGED: { UPINFO* pInfo = UpContext( hwnd ); ASSERT(pInfo); CbUpdateLvAndPbState( pInfo ); return TRUE; } } break; } case WM_COMMAND: { UPINFO* pInfo = UpContext( hwnd ); ASSERT(pInfo); return CbCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } } return FALSE; } VOID CbApply( IN UPINFO* pInfo ) /* Saves the contents of the property page. 'PInfo' is the property sheet ** context. */ { TRACE("CbApply"); if (IsDlgButtonChecked( pInfo->hwndCb, CID_CB_RB_No )) pInfo->user.dwCallbackMode = CBM_No; else if (IsDlgButtonChecked( pInfo->hwndCb, CID_CB_RB_Maybe )) pInfo->user.dwCallbackMode = CBM_Maybe; else pInfo->user.dwCallbackMode = CBM_Yes; CbutilSaveLv( pInfo->hwndLvNumbers, pInfo->user.pdtllistCallback ); } BOOL CbCommand( IN UPINFO* 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("CbCommand(n=%d,i=%d,c=$%x)", (DWORD)wNotification,(DWORD)wId,(ULONG_PTR )hwndCtrl); switch (wId) { case CID_CB_RB_No: case CID_CB_RB_Maybe: case CID_CB_RB_Yes: { if (wNotification == BN_CLICKED) { CbUpdateLvAndPbState( pInfo ); if (wId == CID_CB_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_CB_PB_Edit: { if (wNotification == BN_CLICKED) CbutilEdit( pInfo->hwndCb, pInfo->hwndLvNumbers ); break; } case CID_CB_PB_Delete: { if (wNotification == BN_CLICKED) CbutilDelete( pInfo->hwndCb, pInfo->hwndLvNumbers ); break; } } return FALSE; } BOOL CbInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { UPINFO* pInfo; TRACE("CbInit"); pInfo = UpContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndCb = hwndPage; pInfo->hwndRbNo = GetDlgItem( hwndPage, CID_CB_RB_No ); ASSERT(pInfo->hwndRbNo); pInfo->hwndRbMaybe = GetDlgItem( hwndPage, CID_CB_RB_Maybe ); ASSERT(pInfo->hwndRbMaybe); pInfo->hwndRbYes = GetDlgItem( hwndPage, CID_CB_RB_Yes ); ASSERT(pInfo->hwndRbYes); pInfo->hwndLvNumbers = GetDlgItem( hwndPage, CID_CB_LV_Numbers ); ASSERT(pInfo->hwndLvNumbers); pInfo->hwndPbEdit = GetDlgItem( hwndPage, CID_CB_PB_Edit ); ASSERT(pInfo->hwndPbEdit); pInfo->hwndPbDelete = GetDlgItem( hwndPage, CID_CB_PB_Delete ); ASSERT(pInfo->hwndPbDelete); /* Initialize the listview. */ CbutilFillLvNumbers( pInfo->hwndCb, pInfo->hwndLvNumbers, pInfo->user.pdtllistCallback, FALSE ); /* Set the radio button selection, which triggers appropriate ** enabling/disabling. */ { HWND hwndRb; if (pInfo->user.dwCallbackMode == CBM_No) hwndRb = pInfo->hwndRbNo; else if (pInfo->user.dwCallbackMode == CBM_Maybe) hwndRb = pInfo->hwndRbMaybe; else { ASSERT(pInfo->user.dwCallbackMode==CBM_Yes); hwndRb = pInfo->hwndRbYes; } SendMessage( hwndRb, BM_CLICK, 0, 0 ); } // pmay: If there are no devices available for callback, // add some explanatory text and disable appropriate // controls. Bug 168830 if (ListView_GetItemCount(pInfo->hwndLvNumbers) == 0) { // Uncheck if needed if (Button_GetCheck(pInfo->hwndRbYes)) { Button_SetCheck(pInfo->hwndRbMaybe, TRUE); } // Disable the windows. EnableWindow(pInfo->hwndRbYes, FALSE); EnableWindow(pInfo->hwndLvNumbers, FALSE); } return TRUE; } VOID CbUpdateLvAndPbState( IN UPINFO* 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 fEnableEditButton, fEnableDeleteButton; INT iSel; HWND hwndLv; // By default, we don't enable any buttons fEnableDeleteButton = FALSE; fEnableEditButton = FALSE; // Only enable the list view if Yes is selected // fEnableList = Button_GetCheck( pInfo->hwndRbYes ); if (fEnableList) { hwndLv = pInfo->hwndLvNumbers; if ( ListView_GetSelectedCount( hwndLv ) ) { // The edit button should only be enabled if the // listview is enabled and if one or more // items is selected. fEnableEditButton = TRUE; // // pmay: 213060 // // The delete button is only enabled if all of the selected // devices are not configured on the system. (since only // non-installed devices can be removed from the list). // fEnableDeleteButton = TRUE; for (iSel = ListView_GetNextItem( hwndLv, -1, LVNI_SELECTED ); iSel >= 0; iSel = ListView_GetNextItem( hwndLv, iSel, LVNI_SELECTED ) ) { LV_ITEM item; ZeroMemory(&item, sizeof(item)); item.iItem = iSel; item.mask = LVIF_PARAM; if ( ListView_GetItem(hwndLv, &item) ) { if (((CBCONTEXT*)item.lParam)->fConfigured) { fEnableDeleteButton = FALSE; } } } } } EnableWindow( pInfo->hwndLvNumbers, fEnableList ); EnableWindow( pInfo->hwndPbEdit, fEnableEditButton ); EnableWindow( pInfo->hwndPbDelete, fEnableDeleteButton ); } /*----------------------------------------------------- ** Utilities shared with router version of the listview **----------------------------------------------------- */ VOID CbutilDelete( IN HWND hwndDlg, IN HWND hwndLvNumbers ) /* Called when the Delete button is pressed. 'PInfo' is the dialog ** context. */ { MSGARGS msgargs; INT nResponse; TRACE("CbDelete"); ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_YESNO + MB_ICONEXCLAMATION; nResponse = MsgDlg( hwndDlg, SID_ConfirmDelDevice, &msgargs ); if (nResponse == IDYES) { INT iSel; /* User has confirmed deletion of selected devices, so do it. */ while ((iSel = ListView_GetNextItem( hwndLvNumbers, -1, LVNI_SELECTED )) >= 0) { ListView_DeleteItem( hwndLvNumbers, iSel ); } } } VOID CbutilEdit( IN HWND hwndDlg, IN HWND hwndLvNumbers ) /* Called when the Edit button is pressed. 'HwndDlg' is the page/dialog ** window. 'HwndLvNumbers' is the callback number listview window. */ { INT iSel; TCHAR szBuf[ RAS_MaxCallbackNumber + 1 ]; TCHAR* pszNumber; TRACE("CbutilEdit"); /* Load 'szBuf' with the current phone number of the first selected item. */ iSel = ListView_GetNextItem( hwndLvNumbers, -1, LVNI_SELECTED ); if (iSel < 0) return; szBuf[ 0 ] = TEXT('\0'); ListView_GetItemText( hwndLvNumbers, iSel, 1, szBuf, RAS_MaxCallbackNumber + 1 ); /* Popup dialog to edit the number. */ pszNumber = NULL; if (StringEditorDlg( hwndDlg, szBuf, SID_EcbnTitle, SID_EcbnLabel, RAS_MaxCallbackNumber, HID_ZE_ST_CallbackNumber, &pszNumber )) { /* OK pressed, so change the number on all selected items. */ ASSERT(pszNumber); do { ListView_SetItemText( hwndLvNumbers, iSel, 1, pszNumber ); } while ((iSel = ListView_GetNextItem( hwndLvNumbers, iSel, LVNI_SELECTED )) >= 0); } } VOID CbutilFillLvNumbers( IN HWND hwndDlg, IN HWND hwndLvNumbers, IN DTLLIST* pListCallback, IN BOOL fRouter ) /* Fill the listview with devices and phone numbers. 'HwndDlg' is the ** page/dialog window. 'HwndLvNumbers' is the callback listview. ** 'PListCallback' is the list of CALLBACKINFO. 'FRouter' is true if the ** router ports should be enumerated, or false for regular dial-out ports. ** ** Note: This routine should be called only once. */ { DWORD dwErr; DTLLIST* pListPorts; DTLNODE* pNodeCbi; DTLNODE* pNodePort; INT iItem; TCHAR* psz; TRACE("CbutilFillLvNumbers"); ListView_DeleteAllItems( hwndLvNumbers ); /* Add columns. */ { LV_COLUMN col; TCHAR* pszHeader0; TCHAR* pszHeader1; pszHeader0 = PszFromId( g_hinstDll, SID_DeviceColHead ); pszHeader1 = PszFromId( g_hinstDll, SID_PhoneNumberColHead ); ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT + LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.pszText = (pszHeader0) ? pszHeader0 : TEXT(""); ListView_InsertColumn( hwndLvNumbers, 0, &col ); ZeroMemory( &col, sizeof(col) ); col.mask = LVCF_FMT + LVCF_SUBITEM + LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.pszText = (pszHeader1) ? pszHeader1 : TEXT(""); col.iSubItem = 1; ListView_InsertColumn( hwndLvNumbers, 1, &col ); Free0( pszHeader0 ); Free0( pszHeader1 ); } /* Add the modem and adapter images. */ ListView_SetDeviceImageList( hwndLvNumbers, g_hinstDll ); /* Load listview with callback device/number pairs saved as user ** preferences. */ iItem = 0; ASSERT(pListCallback); for (pNodeCbi = DtlGetFirstNode( pListCallback ); pNodeCbi; pNodeCbi = DtlGetNextNode( pNodeCbi ), ++iItem) { CALLBACKINFO* pCbi; LV_ITEM item; pCbi = (CALLBACKINFO* )DtlGetData( pNodeCbi ); ASSERT(pCbi); ASSERT(pCbi->pszPortName); ASSERT(pCbi->pszDeviceName); ASSERT(pCbi->pszNumber); if (pCbi->dwDeviceType != RASET_Vpn) { psz = PszFromDeviceAndPort( pCbi->pszDeviceName, pCbi->pszPortName ); if (psz) { // pmay: 213060 // // Allocate and initialize the context. // CBCONTEXT * pCbCtx; pCbCtx = (CBCONTEXT*) Malloc (sizeof(CBCONTEXT)); if (pCbCtx == NULL) { continue; } pCbCtx->pszPortName = pCbi->pszPortName; pCbCtx->pszDeviceName = pCbi->pszDeviceName; pCbCtx->dwDeviceType = pCbi->dwDeviceType; pCbCtx->fConfigured = FALSE; ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM; item.iItem = iItem; item.pszText = psz; item.iImage = ((PBDEVICETYPE )pCbi->dwDeviceType == PBDT_Modem) ? DI_Modem : DI_Adapter; item.lParam = (LPARAM )pCbCtx; ListView_InsertItem( hwndLvNumbers, &item ); ListView_SetItemText( hwndLvNumbers, iItem, 1, pCbi->pszNumber ); Free( psz ); } } } /* Add any devices installed but not already in the list. */ dwErr = LoadPortsList2( NULL, &pListPorts, fRouter ); if (dwErr != 0) { ErrorDlg( hwndDlg, SID_OP_LoadPortInfo, dwErr, NULL ); } else { for (pNodePort = DtlGetFirstNode( pListPorts ); pNodePort; pNodePort = DtlGetNextNode( pNodePort )) { PBPORT* pPort = (PBPORT* )DtlGetData( pNodePort ); INT i = -1; BOOL bPortAlreadyInLv = FALSE; ASSERT(pPort); // pmay: 213060 // // Search for the configured item in the list view // while ((i = ListView_GetNextItem( hwndLvNumbers, i, LVNI_ALL )) >= 0) { LV_ITEM item; CBCONTEXT * pCbCtx; ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_PARAM; item.iItem = i; if (!ListView_GetItem( hwndLvNumbers, &item )) { continue; } // Get the context // pCbCtx = (CBCONTEXT*)item.lParam; if (! pCbCtx) { continue; } // If the current item in the list view matches the // current port, then we know that the current item // is configured on the system. if ((lstrcmpi( pPort->pszPort, pCbCtx->pszPortName ) == 0) && (lstrcmpi( pPort->pszDevice, pCbCtx->pszDeviceName ) == 0) ) { bPortAlreadyInLv = TRUE; pCbCtx->fConfigured = TRUE; break; } } if (! bPortAlreadyInLv) { LV_ITEM item; PBDEVICETYPE pbdt; /* The device/port was not in the callback list. Append it ** to the listview with empty phone number. */ if ((pPort->dwType != RASET_Vpn) && (pPort->dwType != RASET_Direct) && (pPort->dwType != RASET_Broadband) ) { psz = PszFromDeviceAndPort( pPort->pszDevice, pPort->pszPort ); if (psz) { // pmay: 213060 // // Allocate and initialize the context. // CBCONTEXT * pCbCtx; pCbCtx = (CBCONTEXT*) Malloc (sizeof(CBCONTEXT)); if (pCbCtx == NULL) { continue; } pCbCtx->pszPortName = pPort->pszPort; pCbCtx->pszDeviceName = pPort->pszDevice; pCbCtx->dwDeviceType = (DWORD) pPort->pbdevicetype; pCbCtx->fConfigured = TRUE; ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM; item.iItem = iItem; item.pszText = psz; item.iImage = (pPort->pbdevicetype == PBDT_Modem) ? DI_Modem : DI_Adapter; item.lParam = (LPARAM ) pCbCtx; ListView_InsertItem( hwndLvNumbers, &item ); ListView_SetItemText( hwndLvNumbers, iItem, 1, TEXT("")); ++iItem; Free( psz ); } } } } DtlDestroyList( pListPorts, DestroyPortNode ); } /* Auto-size columns to look good with the text they contain. */ ListView_SetColumnWidth( hwndLvNumbers, 0, LVSCW_AUTOSIZE_USEHEADER ); ListView_SetColumnWidth( hwndLvNumbers, 1, LVSCW_AUTOSIZE_USEHEADER ); } VOID CbutilLvNumbersCleanup( IN HWND hwndLvNumbers ) /* Cleans up after CbutilFillLvNumbers. */ { INT i; i = -1; while ((i = ListView_GetNextItem( hwndLvNumbers, i, LVNI_ALL )) >= 0) { LV_ITEM item; ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_PARAM; item.iItem = i; if (!ListView_GetItem( hwndLvNumbers, &item )) continue; // Free the context Free0( (PVOID) item.lParam ); } } LVXDRAWINFO* CbutilLvNumbersCallback( IN HWND hwndLv, IN DWORD dwItem ) /* Enhanced list view callback to report drawing information. 'HwndLv' is ** the handle of the list view control. 'DwItem' is the index of the item ** being drawn. ** ** Returns the address of the column information. */ { /* Use "wide selection bar" feature and the other recommended options. ** ** Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'. */ static LVXDRAWINFO info = { 2, 0, LVXDI_Blend50Dis + LVXDI_DxFill, { 0, 0 } }; return &info; } VOID CbutilSaveLv( IN HWND hwndLvNumbers, OUT DTLLIST* pListCallback ) /* Replace list 'pListCallback' contents with that of the listview ** 'hwndLvNumbers'. */ { DTLNODE* pNode; INT i; TRACE("CbutilSaveLv"); /* Empty the list of callback info, then re-populate from the listview. */ while (pNode = DtlGetFirstNode( pListCallback )) { DtlRemoveNode( pListCallback, pNode ); DestroyCallbackNode( pNode ); } i = -1; while ((i = ListView_GetNextItem( hwndLvNumbers, i, LVNI_ALL )) >= 0) { LV_ITEM item; TCHAR* pszDevice; TCHAR* pszPort; TCHAR szDP[ RAS_MaxDeviceName + 2 + MAX_PORT_NAME + 1 + 1 ]; TCHAR szNumber[ RAS_MaxCallbackNumber + 1 ]; szDP[ 0 ] = TEXT('\0'); ZeroMemory( &item, sizeof(item) ); item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = i; item.pszText = szDP; item.cchTextMax = sizeof(szDP) / sizeof(TCHAR); if (!ListView_GetItem( hwndLvNumbers, &item )) continue; szNumber[ 0 ] = TEXT('\0'); ListView_GetItemText( hwndLvNumbers, i, 1, szNumber, RAS_MaxCallbackNumber + 1 ); if (!DeviceAndPortFromPsz( szDP, &pszDevice, &pszPort )) continue; pNode = CreateCallbackNode( pszPort, pszDevice, szNumber, ((CBCONTEXT*)item.lParam)->dwDeviceType ); if (pNode) DtlAddNodeLast( pListCallback, pNode ); Free( pszDevice ); Free( pszPort ); } } /*---------------------------------------------------------------------------- ** Connections Preferences property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK CoDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) { switch (unMsg) { case WM_INITDIALOG: return CoInit( hwnd, (UPARGS* )(((PROPSHEETPAGE* )lparam)->lParam) ); case WM_HELP: case WM_CONTEXTMENU: ContextHelp( g_adwCoHelp, hwnd, unMsg, wparam, lparam ); break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case PSN_APPLY: { BOOL fValid; UPINFO *pUpInfo; TRACE("CoAPPLY"); pUpInfo = UpContext(hwnd); if(NULL != pUpInfo) { CoApply( pUpInfo ); } /* Call UpApply only on first page. */ fValid = UpApply( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, (fValid) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ); return TRUE; } } break; } } return FALSE; } BOOL CoApply( IN UPINFO* pInfo ) // Return true to allow application of property sheet, false // to refuse. { // If we're not the logon user, go ahead and commit // the global phonebook editing flag. if (! pInfo->pArgs->fNoUser ) { BOOL bAllow; bAllow = IsDlgButtonChecked( pInfo->hwndCo, CID_CO_CB_AllowConnectionModification ); if ( (!!bAllow) != (!!pInfo->userLogon.fAllowLogonPhonebookEdits) ) { pInfo->userLogon.fAllowLogonPhonebookEdits = !!bAllow; pInfo->userLogon.fDirty = TRUE; } } return TRUE; } BOOL CoInit( IN HWND hwndPage, IN OUT UPARGS* 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. */ { UPINFO * pInfo = NULL; /* We're first page, so initialize the property sheet. */ pInfo = UpInit( hwndPage, pArgs ); if (!pInfo) return TRUE; pInfo->hwndCo = hwndPage; // Set the flag for allowing phonebook edits if (! pInfo->pArgs->fNoUser ) { Button_SetCheck ( GetDlgItem (pInfo->hwndCo, CID_CO_CB_AllowConnectionModification), pInfo->userLogon.fAllowLogonPhonebookEdits); } return TRUE; } #if 0 /*---------------------------------------------------------------------------- ** General Preferences property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK GpDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the General page of the User Preferences ** property sheet. Parameters and return value are as described for ** standard windows 'DialogProc's. */ { #if 0 TRACE4("GpDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return GpInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: ContextHelp( g_adwGpHelp, hwnd, unMsg, wparam, lparam ); break; case WM_NOTIFY: { switch (((NMHDR* )lparam)->code) { case PSN_RESET: { /* Call UpCancel only on first page. */ TRACE("GpRESET"); UpCancel( hwnd ); SetWindowLong( hwnd, DWLP_MSGRESULT, FALSE ); break; } } break; } case WM_COMMAND: { UPINFO* pInfo = UpContext( hwnd ); ASSERT(pInfo); return GpCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ),(HWND )lparam ); } case WM_DESTROY: { /* UpTerm will handle making sure it only does its ** thing once */ UpTerm( hwnd ); break; } } return FALSE; } VOID GpApply( IN UPINFO* pInfo ) /* Saves the contents of the property page. 'PInfo' is the property sheet ** context. */ { DWORD dwErr; TRACE("GpApply"); pInfo->user.fUseLocation = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_Location ); pInfo->user.fPreviewPhoneNumber = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_Preview ); pInfo->user.fShowConnectStatus = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_Progress ); pInfo->user.fCloseOnDial = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_CloseOnDial ); pInfo->user.fNewEntryWizard = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_UseWizard ); if (pInfo->pArgs->fNoUser) { pInfo->user.fAllowLogonPhonebookEdits = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_PhonebookEdits ); pInfo->user.fAllowLogonLocationEdits = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_LocationEdits ); } else { DWORD dwFlag; pInfo->user.fShowLights = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_Lights ); /* Flip it because the API wants true to mean "disable". */ dwFlag = (DWORD )!IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_AutodialPrompt ); TRACE1("RasSetAutodialParam(%d)",dwFlag); dwErr = g_pRasSetAutodialParam( RASADP_DisableConnectionQuery, &dwFlag, sizeof(dwFlag) ); TRACE1("RasSetAutodialParam=%d",dwErr); } } BOOL GpCommand( IN UPINFO* 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("GpCommand(n=%d,i=%d,c=$%x)", (DWORD)wNotification,(DWORD)wId,(ULONG_PTR )hwndCtrl); if (pInfo->pArgs->fNoUser) { switch (wId) { case CID_GP_CB_Location: case CID_GP_CB_PhonebookEdits: { if (wNotification == BN_CLICKED) GpUpdateCbStates( pInfo ); } break; } } return FALSE; } BOOL GpInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { DWORD dwErr; UPINFO* pInfo; TRACE("GpInit"); pInfo = UpContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndGp = hwndPage; /* Initialize page. */ CheckDlgButton( hwndPage, CID_GP_CB_Preview, pInfo->user.fPreviewPhoneNumber ); CheckDlgButton( hwndPage, CID_GP_CB_Location, pInfo->user.fUseLocation ); CheckDlgButton( hwndPage, CID_GP_CB_Progress, pInfo->user.fShowConnectStatus ); CheckDlgButton( hwndPage, CID_GP_CB_CloseOnDial, pInfo->user.fCloseOnDial ); CheckDlgButton( hwndPage, CID_GP_CB_UseWizard, pInfo->user.fNewEntryWizard ); if (pInfo->pArgs->fNoUser) { /* Edit restriction check boxes for logon mode only. */ CheckDlgButton( hwndPage, CID_GP_CB_PhonebookEdits, pInfo->user.fAllowLogonPhonebookEdits ); CheckDlgButton( hwndPage, CID_GP_CB_LocationEdits, pInfo->user.fAllowLogonLocationEdits ); GpUpdateCbStates( pInfo ); } else { DWORD dwFlag; DWORD cb; /* Start rasmon check box for non-logon mode only. */ CheckDlgButton( hwndPage, CID_GP_CB_Lights, pInfo->user.fShowLights ); /* Autodial prompt check box for non-logon mode only. */ dwFlag = FALSE; cb = sizeof(dwFlag); TRACE("RasGetAutodialParam(DCQ)"); dwErr = g_pRasGetAutodialParam( RASADP_DisableConnectionQuery, &dwFlag, &cb ); TRACE1("RasGetAutodialParam=%d",dwErr); /* Flip it because the API wants true to mean "disable". */ CheckDlgButton( hwndPage, CID_GP_CB_AutodialPrompt, (BOOL )!dwFlag ); } return TRUE; } VOID GpUpdateCbStates( IN UPINFO* pInfo ) /* Updates the enable/disable state of dependent checkboxes. */ { BOOL fLocation; BOOL fPbEdits; ASSERT(pInfo->pArgs->fNoUser); fLocation = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_Location ); if (!fLocation) CheckDlgButton( pInfo->hwndGp, CID_GP_CB_LocationEdits, FALSE ); EnableWindow( GetDlgItem( pInfo->hwndGp, CID_GP_CB_LocationEdits ), fLocation ); fPbEdits = IsDlgButtonChecked( pInfo->hwndGp, CID_GP_CB_PhonebookEdits ); if (!fPbEdits) CheckDlgButton( pInfo->hwndGp, CID_GP_CB_UseWizard, FALSE ); EnableWindow( GetDlgItem( pInfo->hwndGp, CID_GP_CB_UseWizard ), fPbEdits ); } /*---------------------------------------------------------------------------- ** Phone List property page ** Listed alphabetically following dialog proc **---------------------------------------------------------------------------- */ INT_PTR CALLBACK PlDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam ) /* DialogProc callback for the Phone List page of the User Preferences ** Property sheet. Parameters and return value are as described for ** standard windows 'DialogProc's. */ { #if 0 TRACE4("PlDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam); #endif switch (unMsg) { case WM_INITDIALOG: return PlInit( hwnd ); case WM_HELP: case WM_CONTEXTMENU: ContextHelp( g_adwPlHelp, hwnd, unMsg, wparam, lparam ); break; case WM_COMMAND: { UPINFO* pInfo = UpContext( hwnd ); ASSERT(pInfo); return PlCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); } } return FALSE; } BOOL PlApply( IN UPINFO* pInfo ) /* Saves the contents of the property page. 'PInfo' is the property sheet ** context. ** ** Returns false if invalid and can't dismiss, otherwise true. */ { DWORD dwErr; DWORD dwOldMode; DWORD dwNewMode; TCHAR* pszOldPersonal; TCHAR* pszNewPersonal; TCHAR* pszOldAlternate; TCHAR* pszNewAlternate; PBFILE* pFile; TRACE("PlApply"); dwOldMode = pInfo->user.dwPhonebookMode; if (Button_GetCheck( pInfo->hwndRbSystem )) dwNewMode = PBM_System; else if (Button_GetCheck( pInfo->hwndRbPersonal )) dwNewMode = PBM_Personal; else dwNewMode = PBM_Alternate; if (!pInfo->user.pszAlternatePath) pInfo->user.pszAlternatePath = StrDup( TEXT("") ); if (!pInfo->user.pszPersonalFile) pInfo->user.pszPersonalFile = StrDup( TEXT("") ); pszOldAlternate = pInfo->user.pszAlternatePath; pszOldPersonal = pInfo->user.pszPersonalFile; pszNewAlternate = GetText( pInfo->hwndClbAlternates ); if (!pszOldAlternate || !pszOldPersonal || !pszNewAlternate) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadPhonebook, ERROR_NOT_ENOUGH_MEMORY, NULL ); return TRUE; } if (dwNewMode == PBM_Alternate && IsAllWhite( pszNewAlternate )) { /* Alternate phonebook mode, but no path. Tell user to fix it. */ MsgDlg( pInfo->hwndDlg, SID_NoAltPath, NULL ); //PropSheet_SetCurSel( pInfo->hwndDlg, NULL, UP_PlPage ); SetFocus( pInfo->hwndClbAlternates ); ComboBox_SetEditSel( pInfo->hwndClbAlternates, 0, -1 ); return FALSE; } if (dwNewMode == dwOldMode && (dwNewMode != PBM_Alternate || lstrcmpi( pszNewAlternate, pszOldAlternate ) == 0)) { /* User made no changes. */ TRACE("No phonebook change."); Free0( pszNewAlternate ); return TRUE; } /* User changed phonebook settings. */ if (dwNewMode == PBM_Personal && IsAllWhite( pszOldPersonal )) { /* Create the personal phonebook and tell user what happened. */ dwErr = InitPersonalPhonebook( &pszNewPersonal ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_MakePhonebook, dwErr, NULL ); Free( pszNewAlternate ); return TRUE; } ASSERT(pszNewPersonal); MsgDlg( pInfo->hwndDlg, SID_NewPhonebook, NULL ); } else pszNewPersonal = NULL; pInfo->user.dwPhonebookMode = dwNewMode; pInfo->user.pszAlternatePath = pszNewAlternate; if (pszNewPersonal) pInfo->user.pszPersonalFile = pszNewPersonal; if (pInfo->pArgs->ppFile) { /* Open the new phonebook returning the associated file context block ** to the stub API caller. */ pFile = Malloc( sizeof(*pFile) ); if (!pFile) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadPhonebook, ERROR_NOT_ENOUGH_MEMORY, NULL ); Free0( pszNewPersonal ); Free0( pszNewAlternate ); return TRUE; } dwErr = ReadPhonebookFile( NULL, &pInfo->user, NULL, 0, pFile ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_LoadPhonebook, ERROR_NOT_ENOUGH_MEMORY, NULL ); pInfo->user.dwPhonebookMode = dwOldMode; pInfo->user.pszAlternatePath = pszOldAlternate; if (pszNewPersonal) pInfo->user.pszPersonalFile = pszOldPersonal; Free0( pszNewPersonal ); Free0( pszNewAlternate ); Free( pFile ); return TRUE; } /* Return opened file to stub API caller. */ *pInfo->pArgs->ppFile = pFile; } Free0( pszOldAlternate ); if (pszNewPersonal) Free0( pszOldPersonal ); /* Add the edit field path to the list, if it's not already. */ if (!IsAllWhite( pszNewAlternate )) { DTLNODE* pNode; for (pNode = DtlGetFirstNode( pInfo->user.pdtllistPhonebooks ); pNode; pNode = DtlGetNextNode( pNode )) { TCHAR* psz; psz = (TCHAR* )DtlGetData( pNode ); ASSERT(psz); if (lstrcmpi( psz, pszNewAlternate ) == 0) break; } if (!pNode) { pNode = CreatePszNode( pszNewAlternate ); if (pNode) DtlAddNodeFirst( pInfo->user.pdtllistPhonebooks, pNode ); else Free( pszNewAlternate ); } } return TRUE; } BOOL PlCommand( IN UPINFO* 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("PlCommand(n=%d,i=%d,c=$%x)", (DWORD)wNotification,(DWORD)wId,(ULONG_PTR )hwndCtrl); switch (wId) { case CID_PL_RB_SystemList: case CID_PL_RB_PersonalList: { if (wNotification == BN_CLICKED) { EnableWindow( pInfo->hwndClbAlternates, FALSE ); EnableWindow( pInfo->hwndPbBrowse, FALSE ); } return TRUE; } case CID_PL_RB_AlternateList: { if (wNotification == BN_CLICKED) { EnableWindow( pInfo->hwndClbAlternates, TRUE ); EnableWindow( pInfo->hwndPbBrowse, TRUE ); } break; } case CID_PL_PB_Browse: { PlBrowse( pInfo ); return TRUE; } } return FALSE; } VOID PlBrowse( IN UPINFO* pInfo ) /* Called when the Browse button is pressed. 'PInfo' is the property ** sheet context. */ { OPENFILENAME ofn; TCHAR szBuf[ MAX_PATH + 1 ]; TCHAR szFilter[ 64 ]; TCHAR* pszFilterDesc; TCHAR* pszFilter; TCHAR* pszTitle; TCHAR* pszDefExt; TRACE("PlBrowse"); szBuf[ 0 ] = TEXT('\0'); /* Fill in FileOpen dialog parameter buffer. */ pszFilterDesc = PszFromId( g_hinstDll, SID_PbkDescription ); pszFilter = PszFromId( g_hinstDll, SID_PbkFilter ); if (pszFilterDesc && pszFilter) { DWORD dwSize = sizeof(szFilter) / sizeof(TCHAR), dwLen; ZeroMemory( szFilter, sizeof(szFilter) ); lstrcpyn( szFilter, pszFilterDesc, dwSize ); dwLen = lstrlen( szFilter ) + 1; lstrcpyn( szFilter + dwLen, pszFilter, dwSize - dwLen ); } Free0( pszFilterDesc ); Free0( pszFilter ); pszTitle = PszFromId( g_hinstDll, SID_PbkTitle ); pszDefExt = PszFromId( g_hinstDll, SID_PbkDefExt ); ZeroMemory( &ofn, sizeof(ofn) ); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = pInfo->hwndDlg; ofn.hInstance = g_hinstDll; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = szBuf; ofn.nMaxFile = MAX_PATH; ofn.lpstrTitle = pszTitle; ofn.lpstrDefExt = pszDefExt; ofn.Flags = OFN_HIDEREADONLY; { HHOOK hhook; BOOL f; /* Install hook that will get the message box centered on the ** owner window. */ hhook = SetWindowsHookEx( WH_CALLWNDPROC, CenterDlgOnOwnerCallWndProc, g_hinstDll, GetCurrentThreadId() ); TRACE("GetOpenFileName"); f = GetOpenFileName( &ofn ); TRACE1("GetOpenFileName=%d",f); if (hhook) UnhookWindowsHookEx( hhook ); if (f) SetWindowText( pInfo->hwndClbAlternates, ofn.lpstrFile ); } Free0( pszTitle ); Free0( pszDefExt ); } BOOL PlInit( IN HWND hwndPage ) /* Called on WM_INITDIALOG. 'hwndPage' is the handle of the property ** page. ** ** Return false if focus was set, true otherwise. */ { UPINFO* pInfo; TRACE("PlInit"); pInfo = UpContext( hwndPage ); if (!pInfo) return TRUE; /* Initialize page-specific context information. */ pInfo->hwndPl = hwndPage; pInfo->hwndRbSystem = GetDlgItem( hwndPage, CID_PL_RB_SystemList ); ASSERT(pInfo->hwndRbSystem); if (!pInfo->pArgs->fNoUser) { pInfo->hwndRbPersonal = GetDlgItem( hwndPage, CID_PL_RB_PersonalList ); ASSERT(pInfo->hwndRbPersonal); if (pInfo->user.dwPhonebookMode == PBM_Personal) pInfo->user.dwPhonebookMode = PBM_System; } pInfo->hwndRbAlternate = GetDlgItem( hwndPage, CID_PL_RB_AlternateList ); ASSERT(pInfo->hwndRbAlternate); pInfo->hwndClbAlternates = GetDlgItem( hwndPage, CID_PL_CL_Lists ); ASSERT(pInfo->hwndClbAlternates); pInfo->hwndPbBrowse = GetDlgItem( hwndPage, CID_PL_PB_Browse ); ASSERT(pInfo->hwndPbBrowse); /* Load alternate phonebooks list. */ { INT iSel; DTLNODE* pNode; TCHAR* pszSel; pszSel = pInfo->user.pszAlternatePath; iSel = -1; for (pNode = DtlGetFirstNode( pInfo->user.pdtllistPhonebooks ); pNode; pNode = DtlGetNextNode( pNode )) { TCHAR* psz; INT i; psz = (TCHAR* )DtlGetData( pNode ); if (psz) { i = ComboBox_AddString( pInfo->hwndClbAlternates, psz ); if (iSel < 0 && pszSel && lstrcmpi( psz, pszSel ) == 0) iSel = i; } } if (iSel < 0 && pszSel) iSel = ComboBox_AddString( pInfo->hwndClbAlternates, pszSel ); ComboBox_SetCurSel( pInfo->hwndClbAlternates, iSel ); ComboBox_AutoSizeDroppedWidth( pInfo->hwndClbAlternates ); } /* Select the phonebook mode with a pseudo-click which will trigger ** enabling/disabling of combo and button state. */ { HWND hwndRb; if (pInfo->user.dwPhonebookMode == PBM_System) hwndRb = pInfo->hwndRbSystem; else if (pInfo->user.dwPhonebookMode == PBM_Personal) hwndRb = pInfo->hwndRbPersonal; else { ASSERT(pInfo->user.dwPhonebookMode==PBM_Alternate); hwndRb = pInfo->hwndRbAlternate; } SendMessage( hwndRb, BM_CLICK, 0, 0 ); } return TRUE; } #endif