windows-nt/Source/XPSP1/NT/net/tapi/client/cpldialingrulesps.cpp
2020-09-26 16:20:57 +08:00

1099 lines
33 KiB
C++

/****************************************************************************
Copyright (c) 1998-1999 Microsoft Corporation
Module Name: cpldialingrulesps.cpp
Author: toddb - 10/06/98
****************************************************************************/
// Property Sheet stuff for the main page
#include "cplPreComp.h"
#include "cplLocationPS.h"
#include <setupapi.h> // for HDEVINFO
#include <winuser.h> // for HDEVNOTIFY
// Global Variables
HFONT g_hfontBold = NULL;
HINSTANCE g_hInstUI = NULL;
// Prototypes
BOOL CALLBACK SetToForegroundEnumProc( HWND hwnd, LPARAM lParam );
extern "C" INT_PTR CALLBACK LocWizardDlgProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam );
extern "C" LONG EnsureOneLocation (HWND hwnd);
void CountryRunOnce();
class CDialingRulesPropSheet
{
public:
CDialingRulesPropSheet(LPCWSTR pwszAddress, DWORD dwAPIVersion);
~CDialingRulesPropSheet();
#ifdef TRACELOG
DECLARE_TRACELOG_CLASS(CDialingRulesPropSheet)
#endif
LONG DoPropSheet(HWND hwndParent, int iTab);
protected:
LONG CheckForOtherInstances();
static INT_PTR CALLBACK Dailing_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
BOOL Dailing_OnInitDialog(HWND hDlg);
BOOL Dailing_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl);
BOOL Dailing_OnNotify(HWND hwndDlg, LPNMHDR pnmhdr);
void LaunchLocationPropSheet(BOOL bNew, HWND hwndParent);
void DeleteSelectedLocation(HWND hwndList);
void AddLocationToList(HWND hwndList, CLocation *pLoc, BOOL bSelect);
void UpdateLocationInList(HWND hwndList, CLocation *pLocOld, CLocation *pLocNew);
void UpdateControlStates(HWND hDlg);
void SetCheck(HWND hwndList, CLocation * pLoc, int iImage);
static INT_PTR CALLBACK Advanced_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
BOOL Advanced_OnInitDialog(HWND hDlg);
BOOL Advanced_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl);
HANDLE m_hMutex;
DWORD m_dwDefaultCountryID;
CLocation * m_pLocSelected; // pointer the the CLocation for the selected item in the list view.
// can be NULL if no item is selected.
CLocations m_locs; // The locations data used to build the locations list
LPCWSTR m_pwszAddress; // The address (number) we are translating
int m_iSortCol; // which column to sort by
DWORD m_dwAPIVersion; // The version of tapi used to call internalConfig
};
CDialingRulesPropSheet::CDialingRulesPropSheet(LPCWSTR pwszAddress, DWORD dwAPIVersion)
{
m_pwszAddress = pwszAddress;
m_hMutex = NULL;
m_pLocSelected = NULL;
m_dwDefaultCountryID = GetProfileInt(TEXT("intl"), TEXT("iCountry"), 1);
m_iSortCol = 0;
m_dwAPIVersion = dwAPIVersion;
}
CDialingRulesPropSheet::~CDialingRulesPropSheet()
{
if ( m_hMutex )
CloseHandle( m_hMutex );
}
typedef struct tagMODEMDLG
{
HDEVINFO hdi;
HDEVNOTIFY NotificationHandle;
int cSel;
DWORD dwFlags;
} MODEMDLG, FAR * LPMODEMDLG;
LONG CDialingRulesPropSheet::DoPropSheet(HWND hwndParent, int iTab)
{
LONG result;
PROPSHEETHEADER psh;
HPROPSHEETPAGE ahpsp[3];
PROPSHEETPAGE apsp[3];
HINSTANCE hInstModemUI = NULL;
DLGPROC pfnModemDialogProc = NULL;
MODEMDLG md;
md.hdi = INVALID_HANDLE_VALUE;
md.cSel = 0;
md.dwFlags = 0;
result = CheckForOtherInstances();
if ( result )
{
return result;
}
// if iTab is -1 then we only show the dialing rules tab and we hide the modem
// and advanced tabs. When lineTranslateDialog is called we pass -1 for iTab,
// when the CPL is invoked we pass the starting page number as iTab.
if ( -1 != iTab )
{
// we can't link directly to modemui.dll because we live inside TAPI,
// so delay load all the required MODEMUI functions up front.
hInstModemUI = LoadLibrary(TEXT("modemui.dll"));
if (!hInstModemUI)
{
return FALSE;
}
// get proc the functions we need.
pfnModemDialogProc = (DLGPROC)GetProcAddress(hInstModemUI,"ModemCplDlgProc");
if ( !pfnModemDialogProc )
{
FreeLibrary(hInstModemUI);
return FALSE; // Review: Does this return code matter?
}
}
// Review: The old dialing page had some pre-launch configuration to do.
// Some sort of lineConfigure function or something. Check if this is needed.
// We delay the initialization until here
result = (LONG)m_locs.Initialize();
if (result && (result != LINEERR_INIFILECORRUPT))
{
TCHAR szCaption[MAX_INPUT];
TCHAR szMessage[512];
LoadString(GetUIInstance(), IDS_NAME, szCaption, ARRAYSIZE(szCaption));
LoadString(GetUIInstance(), IDS_CANNOT_START_TELEPHONCPL, szMessage, ARRAYSIZE(szMessage));
MessageBox(hwndParent, szMessage, szCaption, MB_OK | MB_ICONWARNING);
return result;
}
// If there are no locations, launch the simple location dialog
if ( 0 == m_locs.GetNumLocations() )
{
// if we are in lineTranslateDialog mode, then we display the simple
int iRes;
iRes = (int)DialogBoxParam(GetUIInstance(), MAKEINTRESOURCE(IDD_SIMPLELOCATION),NULL,
LocWizardDlgProc, (LPARAM)m_dwAPIVersion);
if ( IDOK == iRes )
{
// now we need to re-initalize to pick up the new location
m_locs.Initialize();
// Now we need to figure out the ID of the location we just created
CLocation * pLoc;
m_locs.Reset();
if ( S_OK == m_locs.Next( 1, &pLoc, NULL ) )
{
// Set this ID as the default location
m_locs.SetCurrentLocationID(pLoc->GetLocationID());
CountryRunOnce();
}
// we've already made a commited change, so save the result
m_locs.SaveToRegistry();
result = NO_ERROR;
}
else
{
// If this was lineTranslateDialog and the user canceled the simple location
// dialog then we have already warned them of what might happen. If this is
// a down level legacy call then we return an old error code
if ( m_dwAPIVersion < TAPI_VERSION2_2 )
{
// return an old error code that legacy apps understand
return LINEERR_OPERATIONFAILED;
}
else
{
// as of TAPI_VERSION2_2 we have a new error value just for this case:
return LINEERR_USERCANCELLED;
}
}
}
// Initialize the header:
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_DEFAULT;
psh.hwndParent = hwndParent;
psh.hInstance = GetUIInstance();
psh.hIcon = NULL;
psh.pszCaption = MAKEINTRESOURCE(IDS_NAME);
psh.nPages = (-1!=iTab)?3:1;
psh.nStartPage = (-1!=iTab)?iTab:0;
psh.pfnCallback = NULL;
psh.phpage = ahpsp;
// Now setup the Property Sheet Page
apsp[0].dwSize = sizeof(apsp[0]);
apsp[0].dwFlags = PSP_DEFAULT;
apsp[0].hInstance = GetUIInstance();
apsp[0].pszTemplate = MAKEINTRESOURCE(IDD_MAIN_DIALINGRULES);
apsp[0].pfnDlgProc = CDialingRulesPropSheet::Dailing_DialogProc;
apsp[0].lParam = (LPARAM)this;
ahpsp[0] = CreatePropertySheetPage (&apsp[0]);
if ( -1 != iTab )
{
apsp[1].dwSize = sizeof(apsp[1]);
apsp[1].dwFlags = PSP_DEFAULT;
apsp[1].hInstance = hInstModemUI;
apsp[1].pszTemplate = MAKEINTRESOURCE(20011);
apsp[1].pfnDlgProc = pfnModemDialogProc;
apsp[1].lParam = (LPARAM)&md;
ahpsp[1] = CreatePropertySheetPage (&apsp[1]);
apsp[2].dwSize = sizeof(apsp[2]);
apsp[2].dwFlags = PSP_DEFAULT;
apsp[2].hInstance = GetUIInstance();
apsp[2].pszTemplate = MAKEINTRESOURCE(IDD_MAIN_ADVANCED);
apsp[2].pfnDlgProc = CDialingRulesPropSheet::Advanced_DialogProc;
apsp[2].lParam = 0;
ahpsp[2] = CreatePropertySheetPage (&apsp[2]);
}
if (-1 == PropertySheet( &psh ))
{
result = GetLastError ();
LOG ((TL_ERROR, "PropertySheet failed, error 0x%x", result));
}
// now we're done with modemui, so release it.
if(hInstModemUI)
FreeLibrary(hInstModemUI);
return result;
}
LONG CDialingRulesPropSheet::CheckForOtherInstances()
{
TCHAR szCaption[MAX_INPUT];
if ( !LoadString(GetUIInstance(), IDS_NAME, szCaption, 128) )
{
return LINEERR_OPERATIONFAILED;
}
m_hMutex = CreateMutex (NULL, FALSE, TEXT("tapi_dp_mutex"));
if (!m_hMutex)
{
return LINEERR_OPERATIONFAILED;
}
else if (GetLastError() == ERROR_ALREADY_EXISTS)
{
EnumWindows( SetToForegroundEnumProc, (LPARAM)szCaption );
return LINEERR_INUSE;
}
return 0;
}
BOOL CALLBACK SetToForegroundEnumProc( HWND hwnd, LPARAM lParam )
{
TCHAR szBuf[MAX_INPUT];
GetWindowText (hwnd, szBuf, 128);
if (!lstrcmpi (szBuf, (LPTSTR)lParam))
{
SetForegroundWindow (hwnd);
return FALSE;
}
return TRUE;
}
extern "C" LONG WINAPI internalConfig( HWND hwndParent, PCWSTR pwsz, INT iTab, DWORD dwAPIVersion )
{
CDialingRulesPropSheet drps(pwsz, dwAPIVersion);
return drps.DoPropSheet(hwndParent, iTab);
}
// ********************************************************************
//
// Dialing Rules Property Page functions
//
// ********************************************************************
INT_PTR CALLBACK CDialingRulesPropSheet::Dailing_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CDialingRulesPropSheet* pthis = (CDialingRulesPropSheet*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch(uMsg)
{
case WM_INITDIALOG:
pthis = (CDialingRulesPropSheet*)(((PROPSHEETPAGE*)lParam)->lParam);
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pthis);
return pthis->Dailing_OnInitDialog(hwndDlg);
case WM_COMMAND:
return pthis->Dailing_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam );
case WM_NOTIFY:
return pthis->Dailing_OnNotify(hwndDlg, (LPNMHDR)lParam);
case WM_HELP:
// Process clicks on controls after Context Help mode selected
WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a101HelpIDs);
break;
case WM_CONTEXTMENU:
// Process right-clicks on controls
WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a101HelpIDs);
break;
}
return 0;
}
int CALLBACK Dialing_ListSort(LPARAM lItem1, LPARAM lItem2, LPARAM lCol)
{
if (!lItem1)
{
return -1;
}
if (!lItem2)
{
return 1;
}
CLocation * pLoc1 = (CLocation *)lItem1;
CLocation * pLoc2 = (CLocation *)lItem2;
if ( 1 == lCol)
{
// sort based on column 1, the area code
int iAC1 = StrToIntW(pLoc1->GetAreaCode());
int iAC2 = StrToIntW(pLoc2->GetAreaCode());
if (iAC1!=iAC2)
return iAC1-iAC2;
// fall through if the area codes are identical
}
// sort based on column 0, the location name
return StrCmpIW(pLoc1->GetName(), pLoc2->GetName());
}
BOOL CDialingRulesPropSheet::Dailing_OnInitDialog(HWND hDlg)
{
// Setup the header for the list control
RECT rc;
TCHAR szText[MAX_INPUT];
HWND hwndList = GetDlgItem(hDlg, IDC_LIST);
GetClientRect(hwndList, &rc);
int cxList = rc.right - GetSystemMetrics(SM_CXVSCROLL);
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
lvc.pszText = szText;
struct {
int iStrID;
int cxPercent;
} aData[] = {
{ IDS_LOCATION, 70 },
{ IDS_AREACODE, 30 },
};
for (int i=0; i<ARRAYSIZE(aData); i++)
{
LoadString(GetUIInstance(), aData[i].iStrID, szText, ARRAYSIZE(szText));
lvc.iSubItem = i;
lvc.cx = MulDiv(cxList, aData[i].cxPercent, 100);
ListView_InsertColumn( hwndList, i, &lvc );
}
ListView_SetExtendedListViewStyleEx(hwndList,
LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT,
LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR|ILC_MASK, 2, 2);
HBITMAP hBmp = CreateMappedBitmap(GetUIInstance(), IDB_BUTTONS, 0, NULL, 0);
if (NULL != hBmp)
{
ImageList_AddMasked( himl, hBmp, CLR_DEFAULT);
DeleteObject( hBmp );
}
ListView_SetImageList(hwndList, himl, LVSIL_SMALL);
m_locs.Reset();
CLocation * pLoc;
DWORD dwCurLocID = m_locs.GetCurrentLocationID();
while ( S_OK == m_locs.Next( 1, &pLoc, NULL ) )
{
AddLocationToList( hwndList, pLoc, FALSE );
if ( pLoc->GetLocationID() == dwCurLocID )
{
m_dwDefaultCountryID = pLoc->GetCountryID();
}
}
int iItems = m_locs.GetNumLocations();
UpdateControlStates(hDlg);
ListView_SortItems( hwndList, Dialing_ListSort, m_iSortCol);
SetCheck(hwndList, m_pLocSelected, TRUE);
if (!m_pwszAddress)
{
ShowWindow(GetDlgItem(hDlg,IDC_PHONENUMBERTEXT), SW_HIDE);
}
else if (m_pLocSelected)
{
UpdateSampleString(GetDlgItem(hDlg, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
}
// Select the default item from the location list:
SetFocus(hwndList);
return 0;
}
void CDialingRulesPropSheet::UpdateControlStates(HWND hDlg)
{
int iItems = m_locs.GetNumLocations();
// Set the button states
EnableWindow( GetDlgItem(hDlg, IDC_EDIT), 0!=m_pLocSelected );
EnableWindow( GetDlgItem(hDlg, IDC_SETDEFAULT), 0!=m_pLocSelected );
// if nothing is selected or there is only one item then you cannot
// delete that item
EnableWindow( GetDlgItem(hDlg, IDC_DELETE), ((m_pLocSelected)&&(1<iItems)) );
}
void CDialingRulesPropSheet::AddLocationToList(HWND hwndList, CLocation *pLoc, BOOL bSelected)
{
TCHAR szText[MAX_INPUT];
SHUnicodeToTChar( pLoc->GetName(), szText, ARRAYSIZE(szText) );
LVITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvi.iItem = 0;
lvi.iSubItem = 0;
lvi.pszText = szText;
lvi.iImage = 0;
lvi.lParam = (LONG_PTR)pLoc;
bSelected = bSelected || (pLoc->GetLocationID() == m_locs.GetCurrentLocationID());
if ( bSelected )
{
// Set m_pLocSelected to the current location. It will be selected later.
lvi.mask |= LVIF_STATE;
lvi.state = lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
lvi.iImage = 1;
SetCheck(hwndList, m_pLocSelected, FALSE);
m_pLocSelected = pLoc;
}
int iItem = ListView_InsertItem( hwndList, &lvi );
SHUnicodeToTChar( pLoc->GetAreaCode(), szText, ARRAYSIZE(szText) );
ListView_SetItemText( hwndList, iItem, 1, szText );
}
void CDialingRulesPropSheet::UpdateLocationInList(HWND hwndList, CLocation *pLocOld, CLocation *pLocNew)
{
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = (LPARAM)pLocOld;
int iItem = ListView_FindItem(hwndList,-1,&lvfi);
if (-1 != iItem && pLocNew)
{
TCHAR szText[MAX_INPUT];
SHUnicodeToTChar( pLocNew->GetName(), szText, ARRAYSIZE(szText) );
LVITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.pszText = szText;
lvi.lParam = (LONG_PTR)pLocNew;
ListView_SetItem( hwndList, &lvi );
SHUnicodeToTChar( pLocNew->GetAreaCode(), szText, ARRAYSIZE(szText) );
ListView_SetItemText( hwndList, iItem, 1, szText );
}
else
{
ListView_DeleteItem(hwndList, iItem);
}
}
BOOL CDialingRulesPropSheet::Dailing_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl)
{
switch ( wID )
{
case IDC_NEW:
case IDC_EDIT:
LaunchLocationPropSheet(IDC_NEW == wID, hwndParent);
break;
case IDC_DELETE:
DeleteSelectedLocation(GetDlgItem(hwndParent,IDC_LIST));
break;
default:
return 0;
}
return 1;
}
void CDialingRulesPropSheet::LaunchLocationPropSheet( BOOL bNew, HWND hwndParent )
{
CLocation * pLoc = new CLocation;
if (NULL == pLoc)
{
return;
}
if ( bNew )
{
WCHAR wszNewLoc[MAX_INPUT];
// We offer the default name "My Location" only if there are no locations alread defined.
if ( m_locs.GetNumLocations() > 0 )
{
wszNewLoc[0] = TEXT('\0');
}
else
{
TCHAR szNewLoc[MAX_INPUT];
LoadString(GetUIInstance(), IDS_MYLOCATION, szNewLoc, ARRAYSIZE(szNewLoc));
SHTCharToUnicode(szNewLoc, wszNewLoc, ARRAYSIZE(wszNewLoc));
}
pLoc->Initialize(wszNewLoc,L"",L"",L"",L"",L"",L"",0,m_dwDefaultCountryID,0,LOCATION_USETONEDIALING);
}
else if (m_pLocSelected)
{
CAreaCodeRule * pRule;
pLoc->Initialize(
m_pLocSelected->GetName(),
m_pLocSelected->GetAreaCode(),
m_pLocSelected->GetLongDistanceCarrierCode(),
m_pLocSelected->GetInternationalCarrierCode(),
m_pLocSelected->GetLongDistanceAccessCode(),
m_pLocSelected->GetLocalAccessCode(),
m_pLocSelected->GetDisableCallWaitingCode(),
m_pLocSelected->GetLocationID(),
m_pLocSelected->GetCountryID(),
m_pLocSelected->GetPreferredCardID(),
0,
m_pLocSelected->FromRegistry() );
pLoc->UseCallingCard(m_pLocSelected->HasCallingCard());
pLoc->UseCallWaiting(m_pLocSelected->HasCallWaiting());
pLoc->UseToneDialing(m_pLocSelected->HasToneDialing());
m_pLocSelected->ResetRules();
while ( S_OK == m_pLocSelected->NextRule(1,&pRule,NULL) )
{
CAreaCodeRule * pNewRule = new CAreaCodeRule;
if (NULL == pNewRule)
{
// No more memory, so get out of the loop.
break;
}
pNewRule->Initialize(
pRule->GetAreaCode(),
pRule->GetNumberToDial(),
0,
pRule->GetPrefixList(),
pRule->GetPrefixListSize() );
pNewRule->SetAppliesToAllPrefixes(pRule->HasAppliesToAllPrefixes());
pNewRule->SetDialAreaCode(pRule->HasDialAreaCode());
pNewRule->SetDialNumber(pRule->HasDialNumber());
pLoc->AddRule(pNewRule);
pLoc->Changed();
}
}
else
{
// Out of memory, failed to create pLoc
delete pLoc;
return;
}
CLocationPropSheet nlps( bNew, pLoc, &m_locs, m_pwszAddress );
int iRes = nlps.DoPropSheet(hwndParent);
if ( PSN_APPLY == iRes )
{
HWND hwndList = GetDlgItem(hwndParent,IDC_LIST);
if (bNew)
{
// we don't ask for an ID until we really need it to avoid hitting tapisrv
// any more than we have to.
pLoc->NewID();
m_locs.Add(pLoc);
AddLocationToList(hwndList, pLoc, TRUE);
UpdateControlStates(hwndParent);
}
else
{
m_locs.Replace(m_pLocSelected, pLoc);
UpdateLocationInList(hwndList, m_pLocSelected, pLoc);
m_pLocSelected = pLoc;
}
ListView_SortItems( hwndList, Dialing_ListSort, m_iSortCol);
if ( m_pwszAddress )
{
UpdateSampleString(GetDlgItem(hwndParent, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
}
SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0);
}
else
{
delete pLoc;
}
}
void CDialingRulesPropSheet::DeleteSelectedLocation(HWND hwndList)
{
// First we confirm the delete with the user
TCHAR szText[1024];
TCHAR szTitle[128];
int result;
HWND hwndParent = GetParent(hwndList);
LoadString(GetUIInstance(), IDS_DELETELOCTEXT, szText, ARRAYSIZE(szText));
LoadString(GetUIInstance(), IDS_CONFIRMDELETE, szTitle, ARRAYSIZE(szTitle));
result = SHMessageBoxCheck( hwndParent, szText, szTitle, MB_YESNO, IDYES, TEXT("TAPIDeleteLocation") );
if ( IDYES == result )
{
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = (LPARAM)m_pLocSelected;
int iItem = ListView_FindItem(hwndList,-1,&lvfi);
if ( -1 != iItem )
{
m_locs.Remove(m_pLocSelected);
iItem = DeleteItemAndSelectPrevious( hwndParent, IDC_LIST, iItem, IDC_DELETE, IDC_ADD );
if ( -1 != iItem )
{
LVITEM lvi;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.mask = LVIF_PARAM;
ListView_GetItem( hwndList, &lvi );
// Store the currently selected item
m_pLocSelected = (CLocation *)lvi.lParam;
}
else
{
m_pLocSelected = NULL;
}
UpdateControlStates(hwndParent);
SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0);
}
else
{
// It's really bad if this ever happens (which it shouldn't). This means our
// data is in an unknown state and we might do anything (even destroy data).
LOG((TL_ERROR, "DeleteSelectedLocation: Location Not Found!"));
}
}
}
void CDialingRulesPropSheet::SetCheck(HWND hwndList, CLocation * pLoc, int iImage)
{
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = (LPARAM)pLoc;
int iItem = ListView_FindItem(hwndList,-1,&lvfi);
if (-1 != iItem)
{
LVITEM lvi;
lvi.mask = LVIF_IMAGE;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.iImage = iImage;
ListView_SetItem( hwndList, &lvi );
ListView_EnsureVisible (hwndList, iItem, TRUE);
ListView_Update( hwndList, iItem ); // need the font to be drawn non-bold
}
}
BOOL CDialingRulesPropSheet::Dailing_OnNotify(HWND hwndDlg, LPNMHDR pnmhdr)
{
switch (pnmhdr->idFrom)
{
case IDC_LIST:
#define pnmlv ((LPNMLISTVIEW)pnmhdr)
switch (pnmhdr->code)
{
case LVN_ITEMCHANGED:
if ( (pnmlv->uChanged & LVIF_STATE) && (pnmlv->uNewState & LVIS_SELECTED) )
{
LVITEM lvi;
lvi.iItem = pnmlv->iItem;
lvi.iSubItem = pnmlv->iSubItem;
lvi.mask = LVIF_PARAM;
ListView_GetItem( pnmhdr->hwndFrom, &lvi );
CLocation * pLoc = (CLocation *)lvi.lParam;
// pLoc can be NULL if this is our special "empty list item"
if ( pLoc )
{
m_dwDefaultCountryID = pLoc->GetCountryID();
m_locs.SetCurrentLocationID(pLoc->GetLocationID());
// clear the previous check
SetCheck( pnmhdr->hwndFrom, m_pLocSelected, FALSE );
// Store the currently selected item
m_pLocSelected = pLoc;
// Set the new check
SetCheck( pnmhdr->hwndFrom, m_pLocSelected, TRUE );
if (m_pwszAddress)
{
UpdateSampleString(GetDlgItem(hwndDlg, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
}
}
UpdateControlStates(hwndDlg);
SendMessage(GetParent(hwndDlg),PSM_CHANGED,(WPARAM)hwndDlg,0);
}
break;
case NM_DBLCLK:
if ( !m_pLocSelected )
{
// Do new case
LaunchLocationPropSheet(TRUE,hwndDlg);
}
else
{
// Do edit case
LaunchLocationPropSheet(FALSE,hwndDlg);
}
break;
case NM_CUSTOMDRAW:
#define lplvcd ((LPNMLVCUSTOMDRAW)pnmhdr)
if(lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
{
// Request prepaint notifications for each item.
SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NOTIFYITEMDRAW);
return CDRF_NOTIFYITEMDRAW;
}
if(lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
LVITEM lvi;
lvi.iItem = (int)lplvcd->nmcd.dwItemSpec;
lvi.iSubItem = 0;
lvi.mask = LVIF_PARAM;
ListView_GetItem( pnmhdr->hwndFrom, &lvi );
CLocation * pLoc = (CLocation *)lvi.lParam;
// pLoc can be NULL if this is our special item
if(pLoc && pLoc->GetLocationID() == m_locs.GetCurrentLocationID())
{
if (!g_hfontBold)
{
// we do lazy creation of the font because we need to match whatever
// font the listview control is using and we can't tell which font
// that is until we actually have the HDC for the listbox.
LOGFONT lf;
HFONT hfont = (HFONT)GetCurrentObject(lplvcd->nmcd.hdc, OBJ_FONT);
GetObject(hfont, sizeof(LOGFONT), &lf);
lf.lfWeight += FW_BOLD-FW_NORMAL;
g_hfontBold = CreateFontIndirect(&lf);
}
if (g_hfontBold)
{
SelectObject(lplvcd->nmcd.hdc, g_hfontBold);
SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NEWFONT);
return CDRF_NEWFONT;
}
}
SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_DODEFAULT);
return CDRF_DODEFAULT;
}
return 0;
#undef lplvcd
case LVN_COLUMNCLICK:
m_iSortCol = pnmlv->iSubItem;
ListView_SortItems( pnmhdr->hwndFrom, Dialing_ListSort, m_iSortCol);
break;
case LVN_GETEMPTYTEXT:
#define pnmlvi (((NMLVDISPINFO *)pnmhdr)->item)
LoadString(GetUIInstance(), IDS_CLICKNEW, pnmlvi.pszText, pnmlvi.cchTextMax);
SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,TRUE);
#undef pnmlvi
break;
default:
break;
}
#undef pnmlv
break;
default:
switch (pnmhdr->code)
{
case PSN_APPLY:
// TODO: Ensure that a location is selected in the list
m_locs.SaveToRegistry();
break;
}
return 0;
}
return 1;
}
// ********************************************************************
//
// Advanced Property Page functions (formerly Telephony Drivers page)
//
// ********************************************************************
#include "drv.h"
INT_PTR CALLBACK CDialingRulesPropSheet::Advanced_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CDialingRulesPropSheet* pthis = (CDialingRulesPropSheet*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch(uMsg)
{
case WM_INITDIALOG:
pthis = (CDialingRulesPropSheet*)(((PROPSHEETPAGE*)lParam)->lParam);
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pthis);
return pthis->Advanced_OnInitDialog(hwndDlg);
case WM_COMMAND:
return pthis->Advanced_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam );
case WM_HELP:
// Process clicks on controls after Context Help mode selected
WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a113HelpIDs);
break;
case WM_CONTEXTMENU:
// Process right-clicks on controls
WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a113HelpIDs);
break;
}
return 0;
}
BOOL CDialingRulesPropSheet::Advanced_OnInitDialog(HWND hDlg)
{
UINT uUpdated;
if ( !FillDriverList(GetDlgItem(hDlg, IDC_LIST)) )
{
EndDialog(hDlg, IDCANCEL);
return FALSE;
}
// DWLP_USER is used to store state information about wheter we have disabled
// the property sheet's cancel button. For starters we have not done this.
SetWindowLong( hDlg, DWLP_USER, FALSE );
UpdateDriverDlgButtons (hDlg);
return TRUE;
}
BOOL CDialingRulesPropSheet::Advanced_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl)
{
switch (wID)
{
case IDC_ADD:
// add a new driver
if ( IDOK == DialogBoxParam(
GetUIInstance(),
MAKEINTRESOURCE( IDD_ADD_DRIVER ),
hwndParent,
AddDriver_DialogProc,
0 ) )
{
FillDriverList(GetDlgItem(hwndParent, IDC_LIST));
if (SetWindowLong(hwndParent, DWLP_USER, TRUE) == FALSE)
{
// We have performed a non-cancelable action, update the property sheet to reflect this
PropSheet_CancelToClose( GetParent( hwndParent ) );
}
UpdateDriverDlgButtons(hwndParent);
} // end if
break;
case IDC_LIST:
if ( LBN_SELCHANGE == wNotifyCode )
{
UpdateDriverDlgButtons(hwndParent);
break;
}
else if ( LBN_DBLCLK != wNotifyCode || !IsWindowEnabled( GetDlgItem( hwndParent, IDC_EDIT ) ))
{
// we only fall through if the user double clicked on an editable item
break;
}
// fall through
case IDC_EDIT:
if ( SetupDriver(hwndParent, GetDlgItem(hwndParent, IDC_LIST)) )
{
if ( SetWindowLong( hwndParent, DWLP_USER, TRUE ) == FALSE ) // modified
{
PropSheet_CancelToClose( GetParent(hwndParent) );
}
}
break;
case IDC_REMOVE:
{
TCHAR szCaption[MAX_INPUT];
TCHAR szMessage[512];
LoadString(GetUIInstance(), IDS_REMOVEPROVIDER, szCaption, ARRAYSIZE(szCaption));
LoadString(GetUIInstance(), IDS_CONFIRM_DRIVER_REMOVE, szMessage, ARRAYSIZE(szMessage));
MessageBeep( MB_ICONASTERISK );
if ( IDYES == MessageBox(hwndParent, szMessage, szCaption, MB_YESNO | MB_DEFBUTTON2) )
{
if (SetWindowLong (hwndParent, DWLP_USER, TRUE) == FALSE) // modified
{
PropSheet_CancelToClose( GetParent( hwndParent ) );
}
RemoveSelectedDriver( hwndParent, GetDlgItem(hwndParent, IDC_LIST) );
UpdateDriverDlgButtons (hwndParent);
}
}
break;
}
return 1;
}
HINSTANCE GetUIInstance()
{
if ( NULL == g_hInstUI )
{
g_hInstUI = LoadLibrary(TEXT("tapiui.dll"));
// g_hInstUI = GetModuleHandle(TEXT("tapi32.dll"));
}
return g_hInstUI;
}
LONG EnsureOneLocation (HWND hwnd)
{
CLocations locs;
locs.Initialize();
// If there are no locations, launch the simple location dialog
if ( 0 == locs.GetNumLocations() )
{
// if we are in lineTranslateDialog mode, then we display the simple
int iRes;
iRes = (int)DialogBoxParam(GetUIInstance(), MAKEINTRESOURCE(IDD_SIMPLELOCATION),hwnd,
LocWizardDlgProc, (LPARAM)TAPI_VERSION2_2);
if ( IDOK == iRes )
{
// now we need to re-initalize to pick up the new location
locs.Initialize();
// Now we need to figure out the ID of the location we just created
CLocation * pLoc;
locs.Reset();
if ( S_OK == locs.Next( 1, &pLoc, NULL ) )
{
// Set this ID as the default location
locs.SetCurrentLocationID(pLoc->GetLocationID());
CountryRunOnce();
}
// we've already made a commited change, so save the result
locs.SaveToRegistry();
}
else
{
return LINEERR_USERCANCELLED;
}
}
return S_OK;
}
void CountryRunOnce()
{
//
// This is soft modem workaround provided by unimodem team.
//
// 1. Some vendors set the GCI code incorrectly based on the TAPI location
// key (which is a bad thing L)
// 2. Some modems do not conform to GCI
// 3. Some modems do not correctly accept AT+GCI commands.
// (+GCI is Modems AT commands for setting country)
//
// The conformance check ensures the GCI value is properly sync
// with the TAPI location. It disables GCI if the modem does not conform
// to the GCI spec.
//
// This function can take as long as 15 seconds. We should make sure the UI
// doesn't appear to hang during the call.
//
typedef void (*COUNTRYRUNONCE)();
HMODULE hLib;
hLib=LoadLibrary(TEXT("modemui.dll"));
if (hLib != NULL)
{
COUNTRYRUNONCE Proc;
Proc=(COUNTRYRUNONCE)GetProcAddress(hLib,"CountryRunOnce");
if (Proc != NULL)
{
Proc();
}
FreeLibrary(hLib);
}
}