Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1098 lines
33 KiB

  1. /****************************************************************************
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name: cpldialingrulesps.cpp
  4. Author: toddb - 10/06/98
  5. ****************************************************************************/
  6. // Property Sheet stuff for the main page
  7. #include "cplPreComp.h"
  8. #include "cplLocationPS.h"
  9. #include <setupapi.h> // for HDEVINFO
  10. #include <winuser.h> // for HDEVNOTIFY
  11. // Global Variables
  12. HFONT g_hfontBold = NULL;
  13. HINSTANCE g_hInstUI = NULL;
  14. // Prototypes
  15. BOOL CALLBACK SetToForegroundEnumProc( HWND hwnd, LPARAM lParam );
  16. extern "C" INT_PTR CALLBACK LocWizardDlgProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam );
  17. extern "C" LONG EnsureOneLocation (HWND hwnd);
  18. void CountryRunOnce();
  19. class CDialingRulesPropSheet
  20. {
  21. public:
  22. CDialingRulesPropSheet(LPCWSTR pwszAddress, DWORD dwAPIVersion);
  23. ~CDialingRulesPropSheet();
  24. #ifdef TRACELOG
  25. DECLARE_TRACELOG_CLASS(CDialingRulesPropSheet)
  26. #endif
  27. LONG DoPropSheet(HWND hwndParent, int iTab);
  28. protected:
  29. LONG CheckForOtherInstances();
  30. static INT_PTR CALLBACK Dailing_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  31. BOOL Dailing_OnInitDialog(HWND hDlg);
  32. BOOL Dailing_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl);
  33. BOOL Dailing_OnNotify(HWND hwndDlg, LPNMHDR pnmhdr);
  34. void LaunchLocationPropSheet(BOOL bNew, HWND hwndParent);
  35. void DeleteSelectedLocation(HWND hwndList);
  36. void AddLocationToList(HWND hwndList, CLocation *pLoc, BOOL bSelect);
  37. void UpdateLocationInList(HWND hwndList, CLocation *pLocOld, CLocation *pLocNew);
  38. void UpdateControlStates(HWND hDlg);
  39. void SetCheck(HWND hwndList, CLocation * pLoc, int iImage);
  40. static INT_PTR CALLBACK Advanced_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  41. BOOL Advanced_OnInitDialog(HWND hDlg);
  42. BOOL Advanced_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl);
  43. HANDLE m_hMutex;
  44. DWORD m_dwDefaultCountryID;
  45. CLocation * m_pLocSelected; // pointer the the CLocation for the selected item in the list view.
  46. // can be NULL if no item is selected.
  47. CLocations m_locs; // The locations data used to build the locations list
  48. LPCWSTR m_pwszAddress; // The address (number) we are translating
  49. int m_iSortCol; // which column to sort by
  50. DWORD m_dwAPIVersion; // The version of tapi used to call internalConfig
  51. };
  52. CDialingRulesPropSheet::CDialingRulesPropSheet(LPCWSTR pwszAddress, DWORD dwAPIVersion)
  53. {
  54. m_pwszAddress = pwszAddress;
  55. m_hMutex = NULL;
  56. m_pLocSelected = NULL;
  57. m_dwDefaultCountryID = GetProfileInt(TEXT("intl"), TEXT("iCountry"), 1);
  58. m_iSortCol = 0;
  59. m_dwAPIVersion = dwAPIVersion;
  60. }
  61. CDialingRulesPropSheet::~CDialingRulesPropSheet()
  62. {
  63. if ( m_hMutex )
  64. CloseHandle( m_hMutex );
  65. }
  66. typedef struct tagMODEMDLG
  67. {
  68. HDEVINFO hdi;
  69. HDEVNOTIFY NotificationHandle;
  70. int cSel;
  71. DWORD dwFlags;
  72. } MODEMDLG, FAR * LPMODEMDLG;
  73. LONG CDialingRulesPropSheet::DoPropSheet(HWND hwndParent, int iTab)
  74. {
  75. LONG result;
  76. PROPSHEETHEADER psh;
  77. HPROPSHEETPAGE ahpsp[3];
  78. PROPSHEETPAGE apsp[3];
  79. HINSTANCE hInstModemUI = NULL;
  80. DLGPROC pfnModemDialogProc = NULL;
  81. MODEMDLG md;
  82. md.hdi = INVALID_HANDLE_VALUE;
  83. md.cSel = 0;
  84. md.dwFlags = 0;
  85. result = CheckForOtherInstances();
  86. if ( result )
  87. {
  88. return result;
  89. }
  90. // if iTab is -1 then we only show the dialing rules tab and we hide the modem
  91. // and advanced tabs. When lineTranslateDialog is called we pass -1 for iTab,
  92. // when the CPL is invoked we pass the starting page number as iTab.
  93. if ( -1 != iTab )
  94. {
  95. // we can't link directly to modemui.dll because we live inside TAPI,
  96. // so delay load all the required MODEMUI functions up front.
  97. hInstModemUI = LoadLibrary(TEXT("modemui.dll"));
  98. if (!hInstModemUI)
  99. {
  100. return FALSE;
  101. }
  102. // get proc the functions we need.
  103. pfnModemDialogProc = (DLGPROC)GetProcAddress(hInstModemUI,"ModemCplDlgProc");
  104. if ( !pfnModemDialogProc )
  105. {
  106. FreeLibrary(hInstModemUI);
  107. return FALSE; // Review: Does this return code matter?
  108. }
  109. }
  110. // Review: The old dialing page had some pre-launch configuration to do.
  111. // Some sort of lineConfigure function or something. Check if this is needed.
  112. // We delay the initialization until here
  113. result = (LONG)m_locs.Initialize();
  114. if (result && (result != LINEERR_INIFILECORRUPT))
  115. {
  116. TCHAR szCaption[MAX_INPUT];
  117. TCHAR szMessage[512];
  118. LoadString(GetUIInstance(), IDS_NAME, szCaption, ARRAYSIZE(szCaption));
  119. LoadString(GetUIInstance(), IDS_CANNOT_START_TELEPHONCPL, szMessage, ARRAYSIZE(szMessage));
  120. MessageBox(hwndParent, szMessage, szCaption, MB_OK | MB_ICONWARNING);
  121. return result;
  122. }
  123. // If there are no locations, launch the simple location dialog
  124. if ( 0 == m_locs.GetNumLocations() )
  125. {
  126. // if we are in lineTranslateDialog mode, then we display the simple
  127. int iRes;
  128. iRes = (int)DialogBoxParam(GetUIInstance(), MAKEINTRESOURCE(IDD_SIMPLELOCATION),NULL,
  129. LocWizardDlgProc, (LPARAM)m_dwAPIVersion);
  130. if ( IDOK == iRes )
  131. {
  132. // now we need to re-initalize to pick up the new location
  133. m_locs.Initialize();
  134. // Now we need to figure out the ID of the location we just created
  135. CLocation * pLoc;
  136. m_locs.Reset();
  137. if ( S_OK == m_locs.Next( 1, &pLoc, NULL ) )
  138. {
  139. // Set this ID as the default location
  140. m_locs.SetCurrentLocationID(pLoc->GetLocationID());
  141. CountryRunOnce();
  142. }
  143. // we've already made a commited change, so save the result
  144. m_locs.SaveToRegistry();
  145. result = NO_ERROR;
  146. }
  147. else
  148. {
  149. // If this was lineTranslateDialog and the user canceled the simple location
  150. // dialog then we have already warned them of what might happen. If this is
  151. // a down level legacy call then we return an old error code
  152. if ( m_dwAPIVersion < TAPI_VERSION2_2 )
  153. {
  154. // return an old error code that legacy apps understand
  155. return LINEERR_OPERATIONFAILED;
  156. }
  157. else
  158. {
  159. // as of TAPI_VERSION2_2 we have a new error value just for this case:
  160. return LINEERR_USERCANCELLED;
  161. }
  162. }
  163. }
  164. // Initialize the header:
  165. psh.dwSize = sizeof(psh);
  166. psh.dwFlags = PSH_DEFAULT;
  167. psh.hwndParent = hwndParent;
  168. psh.hInstance = GetUIInstance();
  169. psh.hIcon = NULL;
  170. psh.pszCaption = MAKEINTRESOURCE(IDS_NAME);
  171. psh.nPages = (-1!=iTab)?3:1;
  172. psh.nStartPage = (-1!=iTab)?iTab:0;
  173. psh.pfnCallback = NULL;
  174. psh.phpage = ahpsp;
  175. // Now setup the Property Sheet Page
  176. apsp[0].dwSize = sizeof(apsp[0]);
  177. apsp[0].dwFlags = PSP_DEFAULT;
  178. apsp[0].hInstance = GetUIInstance();
  179. apsp[0].pszTemplate = MAKEINTRESOURCE(IDD_MAIN_DIALINGRULES);
  180. apsp[0].pfnDlgProc = CDialingRulesPropSheet::Dailing_DialogProc;
  181. apsp[0].lParam = (LPARAM)this;
  182. ahpsp[0] = CreatePropertySheetPage (&apsp[0]);
  183. if ( -1 != iTab )
  184. {
  185. apsp[1].dwSize = sizeof(apsp[1]);
  186. apsp[1].dwFlags = PSP_DEFAULT;
  187. apsp[1].hInstance = hInstModemUI;
  188. apsp[1].pszTemplate = MAKEINTRESOURCE(20011);
  189. apsp[1].pfnDlgProc = pfnModemDialogProc;
  190. apsp[1].lParam = (LPARAM)&md;
  191. ahpsp[1] = CreatePropertySheetPage (&apsp[1]);
  192. apsp[2].dwSize = sizeof(apsp[2]);
  193. apsp[2].dwFlags = PSP_DEFAULT;
  194. apsp[2].hInstance = GetUIInstance();
  195. apsp[2].pszTemplate = MAKEINTRESOURCE(IDD_MAIN_ADVANCED);
  196. apsp[2].pfnDlgProc = CDialingRulesPropSheet::Advanced_DialogProc;
  197. apsp[2].lParam = 0;
  198. ahpsp[2] = CreatePropertySheetPage (&apsp[2]);
  199. }
  200. if (-1 == PropertySheet( &psh ))
  201. {
  202. result = GetLastError ();
  203. LOG ((TL_ERROR, "PropertySheet failed, error 0x%x", result));
  204. }
  205. // now we're done with modemui, so release it.
  206. if(hInstModemUI)
  207. FreeLibrary(hInstModemUI);
  208. return result;
  209. }
  210. LONG CDialingRulesPropSheet::CheckForOtherInstances()
  211. {
  212. TCHAR szCaption[MAX_INPUT];
  213. if ( !LoadString(GetUIInstance(), IDS_NAME, szCaption, 128) )
  214. {
  215. return LINEERR_OPERATIONFAILED;
  216. }
  217. m_hMutex = CreateMutex (NULL, FALSE, TEXT("tapi_dp_mutex"));
  218. if (!m_hMutex)
  219. {
  220. return LINEERR_OPERATIONFAILED;
  221. }
  222. else if (GetLastError() == ERROR_ALREADY_EXISTS)
  223. {
  224. EnumWindows( SetToForegroundEnumProc, (LPARAM)szCaption );
  225. return LINEERR_INUSE;
  226. }
  227. return 0;
  228. }
  229. BOOL CALLBACK SetToForegroundEnumProc( HWND hwnd, LPARAM lParam )
  230. {
  231. TCHAR szBuf[MAX_INPUT];
  232. GetWindowText (hwnd, szBuf, 128);
  233. if (!lstrcmpi (szBuf, (LPTSTR)lParam))
  234. {
  235. SetForegroundWindow (hwnd);
  236. return FALSE;
  237. }
  238. return TRUE;
  239. }
  240. extern "C" LONG WINAPI internalConfig( HWND hwndParent, PCWSTR pwsz, INT iTab, DWORD dwAPIVersion )
  241. {
  242. CDialingRulesPropSheet drps(pwsz, dwAPIVersion);
  243. return drps.DoPropSheet(hwndParent, iTab);
  244. }
  245. // ********************************************************************
  246. //
  247. // Dialing Rules Property Page functions
  248. //
  249. // ********************************************************************
  250. INT_PTR CALLBACK CDialingRulesPropSheet::Dailing_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  251. {
  252. CDialingRulesPropSheet* pthis = (CDialingRulesPropSheet*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  253. switch(uMsg)
  254. {
  255. case WM_INITDIALOG:
  256. pthis = (CDialingRulesPropSheet*)(((PROPSHEETPAGE*)lParam)->lParam);
  257. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pthis);
  258. return pthis->Dailing_OnInitDialog(hwndDlg);
  259. case WM_COMMAND:
  260. return pthis->Dailing_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam );
  261. case WM_NOTIFY:
  262. return pthis->Dailing_OnNotify(hwndDlg, (LPNMHDR)lParam);
  263. case WM_HELP:
  264. // Process clicks on controls after Context Help mode selected
  265. WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a101HelpIDs);
  266. break;
  267. case WM_CONTEXTMENU:
  268. // Process right-clicks on controls
  269. WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a101HelpIDs);
  270. break;
  271. }
  272. return 0;
  273. }
  274. int CALLBACK Dialing_ListSort(LPARAM lItem1, LPARAM lItem2, LPARAM lCol)
  275. {
  276. if (!lItem1)
  277. {
  278. return -1;
  279. }
  280. if (!lItem2)
  281. {
  282. return 1;
  283. }
  284. CLocation * pLoc1 = (CLocation *)lItem1;
  285. CLocation * pLoc2 = (CLocation *)lItem2;
  286. if ( 1 == lCol)
  287. {
  288. // sort based on column 1, the area code
  289. int iAC1 = StrToIntW(pLoc1->GetAreaCode());
  290. int iAC2 = StrToIntW(pLoc2->GetAreaCode());
  291. if (iAC1!=iAC2)
  292. return iAC1-iAC2;
  293. // fall through if the area codes are identical
  294. }
  295. // sort based on column 0, the location name
  296. return StrCmpIW(pLoc1->GetName(), pLoc2->GetName());
  297. }
  298. BOOL CDialingRulesPropSheet::Dailing_OnInitDialog(HWND hDlg)
  299. {
  300. // Setup the header for the list control
  301. RECT rc;
  302. TCHAR szText[MAX_INPUT];
  303. HWND hwndList = GetDlgItem(hDlg, IDC_LIST);
  304. GetClientRect(hwndList, &rc);
  305. int cxList = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  306. LVCOLUMN lvc;
  307. lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  308. lvc.pszText = szText;
  309. struct {
  310. int iStrID;
  311. int cxPercent;
  312. } aData[] = {
  313. { IDS_LOCATION, 70 },
  314. { IDS_AREACODE, 30 },
  315. };
  316. for (int i=0; i<ARRAYSIZE(aData); i++)
  317. {
  318. LoadString(GetUIInstance(), aData[i].iStrID, szText, ARRAYSIZE(szText));
  319. lvc.iSubItem = i;
  320. lvc.cx = MulDiv(cxList, aData[i].cxPercent, 100);
  321. ListView_InsertColumn( hwndList, i, &lvc );
  322. }
  323. ListView_SetExtendedListViewStyleEx(hwndList,
  324. LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT,
  325. LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
  326. HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR|ILC_MASK, 2, 2);
  327. HBITMAP hBmp = CreateMappedBitmap(GetUIInstance(), IDB_BUTTONS, 0, NULL, 0);
  328. if (NULL != hBmp)
  329. {
  330. ImageList_AddMasked( himl, hBmp, CLR_DEFAULT);
  331. DeleteObject( hBmp );
  332. }
  333. ListView_SetImageList(hwndList, himl, LVSIL_SMALL);
  334. m_locs.Reset();
  335. CLocation * pLoc;
  336. DWORD dwCurLocID = m_locs.GetCurrentLocationID();
  337. while ( S_OK == m_locs.Next( 1, &pLoc, NULL ) )
  338. {
  339. AddLocationToList( hwndList, pLoc, FALSE );
  340. if ( pLoc->GetLocationID() == dwCurLocID )
  341. {
  342. m_dwDefaultCountryID = pLoc->GetCountryID();
  343. }
  344. }
  345. int iItems = m_locs.GetNumLocations();
  346. UpdateControlStates(hDlg);
  347. ListView_SortItems( hwndList, Dialing_ListSort, m_iSortCol);
  348. SetCheck(hwndList, m_pLocSelected, TRUE);
  349. if (!m_pwszAddress)
  350. {
  351. ShowWindow(GetDlgItem(hDlg,IDC_PHONENUMBERTEXT), SW_HIDE);
  352. }
  353. else if (m_pLocSelected)
  354. {
  355. UpdateSampleString(GetDlgItem(hDlg, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
  356. }
  357. // Select the default item from the location list:
  358. SetFocus(hwndList);
  359. return 0;
  360. }
  361. void CDialingRulesPropSheet::UpdateControlStates(HWND hDlg)
  362. {
  363. int iItems = m_locs.GetNumLocations();
  364. // Set the button states
  365. EnableWindow( GetDlgItem(hDlg, IDC_EDIT), 0!=m_pLocSelected );
  366. EnableWindow( GetDlgItem(hDlg, IDC_SETDEFAULT), 0!=m_pLocSelected );
  367. // if nothing is selected or there is only one item then you cannot
  368. // delete that item
  369. EnableWindow( GetDlgItem(hDlg, IDC_DELETE), ((m_pLocSelected)&&(1<iItems)) );
  370. }
  371. void CDialingRulesPropSheet::AddLocationToList(HWND hwndList, CLocation *pLoc, BOOL bSelected)
  372. {
  373. TCHAR szText[MAX_INPUT];
  374. SHUnicodeToTChar( pLoc->GetName(), szText, ARRAYSIZE(szText) );
  375. LVITEM lvi;
  376. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  377. lvi.iItem = 0;
  378. lvi.iSubItem = 0;
  379. lvi.pszText = szText;
  380. lvi.iImage = 0;
  381. lvi.lParam = (LONG_PTR)pLoc;
  382. bSelected = bSelected || (pLoc->GetLocationID() == m_locs.GetCurrentLocationID());
  383. if ( bSelected )
  384. {
  385. // Set m_pLocSelected to the current location. It will be selected later.
  386. lvi.mask |= LVIF_STATE;
  387. lvi.state = lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  388. lvi.iImage = 1;
  389. SetCheck(hwndList, m_pLocSelected, FALSE);
  390. m_pLocSelected = pLoc;
  391. }
  392. int iItem = ListView_InsertItem( hwndList, &lvi );
  393. SHUnicodeToTChar( pLoc->GetAreaCode(), szText, ARRAYSIZE(szText) );
  394. ListView_SetItemText( hwndList, iItem, 1, szText );
  395. }
  396. void CDialingRulesPropSheet::UpdateLocationInList(HWND hwndList, CLocation *pLocOld, CLocation *pLocNew)
  397. {
  398. LVFINDINFO lvfi;
  399. lvfi.flags = LVFI_PARAM;
  400. lvfi.lParam = (LPARAM)pLocOld;
  401. int iItem = ListView_FindItem(hwndList,-1,&lvfi);
  402. if (-1 != iItem && pLocNew)
  403. {
  404. TCHAR szText[MAX_INPUT];
  405. SHUnicodeToTChar( pLocNew->GetName(), szText, ARRAYSIZE(szText) );
  406. LVITEM lvi;
  407. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  408. lvi.iItem = iItem;
  409. lvi.iSubItem = 0;
  410. lvi.pszText = szText;
  411. lvi.lParam = (LONG_PTR)pLocNew;
  412. ListView_SetItem( hwndList, &lvi );
  413. SHUnicodeToTChar( pLocNew->GetAreaCode(), szText, ARRAYSIZE(szText) );
  414. ListView_SetItemText( hwndList, iItem, 1, szText );
  415. }
  416. else
  417. {
  418. ListView_DeleteItem(hwndList, iItem);
  419. }
  420. }
  421. BOOL CDialingRulesPropSheet::Dailing_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl)
  422. {
  423. switch ( wID )
  424. {
  425. case IDC_NEW:
  426. case IDC_EDIT:
  427. LaunchLocationPropSheet(IDC_NEW == wID, hwndParent);
  428. break;
  429. case IDC_DELETE:
  430. DeleteSelectedLocation(GetDlgItem(hwndParent,IDC_LIST));
  431. break;
  432. default:
  433. return 0;
  434. }
  435. return 1;
  436. }
  437. void CDialingRulesPropSheet::LaunchLocationPropSheet( BOOL bNew, HWND hwndParent )
  438. {
  439. CLocation * pLoc = new CLocation;
  440. if (NULL == pLoc)
  441. {
  442. return;
  443. }
  444. if ( bNew )
  445. {
  446. WCHAR wszNewLoc[MAX_INPUT];
  447. // We offer the default name "My Location" only if there are no locations alread defined.
  448. if ( m_locs.GetNumLocations() > 0 )
  449. {
  450. wszNewLoc[0] = TEXT('\0');
  451. }
  452. else
  453. {
  454. TCHAR szNewLoc[MAX_INPUT];
  455. LoadString(GetUIInstance(), IDS_MYLOCATION, szNewLoc, ARRAYSIZE(szNewLoc));
  456. SHTCharToUnicode(szNewLoc, wszNewLoc, ARRAYSIZE(wszNewLoc));
  457. }
  458. pLoc->Initialize(wszNewLoc,L"",L"",L"",L"",L"",L"",0,m_dwDefaultCountryID,0,LOCATION_USETONEDIALING);
  459. }
  460. else if (m_pLocSelected)
  461. {
  462. CAreaCodeRule * pRule;
  463. pLoc->Initialize(
  464. m_pLocSelected->GetName(),
  465. m_pLocSelected->GetAreaCode(),
  466. m_pLocSelected->GetLongDistanceCarrierCode(),
  467. m_pLocSelected->GetInternationalCarrierCode(),
  468. m_pLocSelected->GetLongDistanceAccessCode(),
  469. m_pLocSelected->GetLocalAccessCode(),
  470. m_pLocSelected->GetDisableCallWaitingCode(),
  471. m_pLocSelected->GetLocationID(),
  472. m_pLocSelected->GetCountryID(),
  473. m_pLocSelected->GetPreferredCardID(),
  474. 0,
  475. m_pLocSelected->FromRegistry() );
  476. pLoc->UseCallingCard(m_pLocSelected->HasCallingCard());
  477. pLoc->UseCallWaiting(m_pLocSelected->HasCallWaiting());
  478. pLoc->UseToneDialing(m_pLocSelected->HasToneDialing());
  479. m_pLocSelected->ResetRules();
  480. while ( S_OK == m_pLocSelected->NextRule(1,&pRule,NULL) )
  481. {
  482. CAreaCodeRule * pNewRule = new CAreaCodeRule;
  483. if (NULL == pNewRule)
  484. {
  485. // No more memory, so get out of the loop.
  486. break;
  487. }
  488. pNewRule->Initialize(
  489. pRule->GetAreaCode(),
  490. pRule->GetNumberToDial(),
  491. 0,
  492. pRule->GetPrefixList(),
  493. pRule->GetPrefixListSize() );
  494. pNewRule->SetAppliesToAllPrefixes(pRule->HasAppliesToAllPrefixes());
  495. pNewRule->SetDialAreaCode(pRule->HasDialAreaCode());
  496. pNewRule->SetDialNumber(pRule->HasDialNumber());
  497. pLoc->AddRule(pNewRule);
  498. pLoc->Changed();
  499. }
  500. }
  501. else
  502. {
  503. // Out of memory, failed to create pLoc
  504. delete pLoc;
  505. return;
  506. }
  507. CLocationPropSheet nlps( bNew, pLoc, &m_locs, m_pwszAddress );
  508. int iRes = nlps.DoPropSheet(hwndParent);
  509. if ( PSN_APPLY == iRes )
  510. {
  511. HWND hwndList = GetDlgItem(hwndParent,IDC_LIST);
  512. if (bNew)
  513. {
  514. // we don't ask for an ID until we really need it to avoid hitting tapisrv
  515. // any more than we have to.
  516. pLoc->NewID();
  517. m_locs.Add(pLoc);
  518. AddLocationToList(hwndList, pLoc, TRUE);
  519. UpdateControlStates(hwndParent);
  520. }
  521. else
  522. {
  523. m_locs.Replace(m_pLocSelected, pLoc);
  524. UpdateLocationInList(hwndList, m_pLocSelected, pLoc);
  525. m_pLocSelected = pLoc;
  526. }
  527. ListView_SortItems( hwndList, Dialing_ListSort, m_iSortCol);
  528. if ( m_pwszAddress )
  529. {
  530. UpdateSampleString(GetDlgItem(hwndParent, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
  531. }
  532. SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0);
  533. }
  534. else
  535. {
  536. delete pLoc;
  537. }
  538. }
  539. void CDialingRulesPropSheet::DeleteSelectedLocation(HWND hwndList)
  540. {
  541. // First we confirm the delete with the user
  542. TCHAR szText[1024];
  543. TCHAR szTitle[128];
  544. int result;
  545. HWND hwndParent = GetParent(hwndList);
  546. LoadString(GetUIInstance(), IDS_DELETELOCTEXT, szText, ARRAYSIZE(szText));
  547. LoadString(GetUIInstance(), IDS_CONFIRMDELETE, szTitle, ARRAYSIZE(szTitle));
  548. result = SHMessageBoxCheck( hwndParent, szText, szTitle, MB_YESNO, IDYES, TEXT("TAPIDeleteLocation") );
  549. if ( IDYES == result )
  550. {
  551. LVFINDINFO lvfi;
  552. lvfi.flags = LVFI_PARAM;
  553. lvfi.lParam = (LPARAM)m_pLocSelected;
  554. int iItem = ListView_FindItem(hwndList,-1,&lvfi);
  555. if ( -1 != iItem )
  556. {
  557. m_locs.Remove(m_pLocSelected);
  558. iItem = DeleteItemAndSelectPrevious( hwndParent, IDC_LIST, iItem, IDC_DELETE, IDC_ADD );
  559. if ( -1 != iItem )
  560. {
  561. LVITEM lvi;
  562. lvi.iItem = iItem;
  563. lvi.iSubItem = 0;
  564. lvi.mask = LVIF_PARAM;
  565. ListView_GetItem( hwndList, &lvi );
  566. // Store the currently selected item
  567. m_pLocSelected = (CLocation *)lvi.lParam;
  568. }
  569. else
  570. {
  571. m_pLocSelected = NULL;
  572. }
  573. UpdateControlStates(hwndParent);
  574. SendMessage(GetParent(hwndParent),PSM_CHANGED,(WPARAM)hwndParent,0);
  575. }
  576. else
  577. {
  578. // It's really bad if this ever happens (which it shouldn't). This means our
  579. // data is in an unknown state and we might do anything (even destroy data).
  580. LOG((TL_ERROR, "DeleteSelectedLocation: Location Not Found!"));
  581. }
  582. }
  583. }
  584. void CDialingRulesPropSheet::SetCheck(HWND hwndList, CLocation * pLoc, int iImage)
  585. {
  586. LVFINDINFO lvfi;
  587. lvfi.flags = LVFI_PARAM;
  588. lvfi.lParam = (LPARAM)pLoc;
  589. int iItem = ListView_FindItem(hwndList,-1,&lvfi);
  590. if (-1 != iItem)
  591. {
  592. LVITEM lvi;
  593. lvi.mask = LVIF_IMAGE;
  594. lvi.iItem = iItem;
  595. lvi.iSubItem = 0;
  596. lvi.iImage = iImage;
  597. ListView_SetItem( hwndList, &lvi );
  598. ListView_EnsureVisible (hwndList, iItem, TRUE);
  599. ListView_Update( hwndList, iItem ); // need the font to be drawn non-bold
  600. }
  601. }
  602. BOOL CDialingRulesPropSheet::Dailing_OnNotify(HWND hwndDlg, LPNMHDR pnmhdr)
  603. {
  604. switch (pnmhdr->idFrom)
  605. {
  606. case IDC_LIST:
  607. #define pnmlv ((LPNMLISTVIEW)pnmhdr)
  608. switch (pnmhdr->code)
  609. {
  610. case LVN_ITEMCHANGED:
  611. if ( (pnmlv->uChanged & LVIF_STATE) && (pnmlv->uNewState & LVIS_SELECTED) )
  612. {
  613. LVITEM lvi;
  614. lvi.iItem = pnmlv->iItem;
  615. lvi.iSubItem = pnmlv->iSubItem;
  616. lvi.mask = LVIF_PARAM;
  617. ListView_GetItem( pnmhdr->hwndFrom, &lvi );
  618. CLocation * pLoc = (CLocation *)lvi.lParam;
  619. // pLoc can be NULL if this is our special "empty list item"
  620. if ( pLoc )
  621. {
  622. m_dwDefaultCountryID = pLoc->GetCountryID();
  623. m_locs.SetCurrentLocationID(pLoc->GetLocationID());
  624. // clear the previous check
  625. SetCheck( pnmhdr->hwndFrom, m_pLocSelected, FALSE );
  626. // Store the currently selected item
  627. m_pLocSelected = pLoc;
  628. // Set the new check
  629. SetCheck( pnmhdr->hwndFrom, m_pLocSelected, TRUE );
  630. if (m_pwszAddress)
  631. {
  632. UpdateSampleString(GetDlgItem(hwndDlg, IDC_PHONENUMBERSAMPLE), m_pLocSelected, m_pwszAddress, NULL);
  633. }
  634. }
  635. UpdateControlStates(hwndDlg);
  636. SendMessage(GetParent(hwndDlg),PSM_CHANGED,(WPARAM)hwndDlg,0);
  637. }
  638. break;
  639. case NM_DBLCLK:
  640. if ( !m_pLocSelected )
  641. {
  642. // Do new case
  643. LaunchLocationPropSheet(TRUE,hwndDlg);
  644. }
  645. else
  646. {
  647. // Do edit case
  648. LaunchLocationPropSheet(FALSE,hwndDlg);
  649. }
  650. break;
  651. case NM_CUSTOMDRAW:
  652. #define lplvcd ((LPNMLVCUSTOMDRAW)pnmhdr)
  653. if(lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
  654. {
  655. // Request prepaint notifications for each item.
  656. SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NOTIFYITEMDRAW);
  657. return CDRF_NOTIFYITEMDRAW;
  658. }
  659. if(lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
  660. {
  661. LVITEM lvi;
  662. lvi.iItem = (int)lplvcd->nmcd.dwItemSpec;
  663. lvi.iSubItem = 0;
  664. lvi.mask = LVIF_PARAM;
  665. ListView_GetItem( pnmhdr->hwndFrom, &lvi );
  666. CLocation * pLoc = (CLocation *)lvi.lParam;
  667. // pLoc can be NULL if this is our special item
  668. if(pLoc && pLoc->GetLocationID() == m_locs.GetCurrentLocationID())
  669. {
  670. if (!g_hfontBold)
  671. {
  672. // we do lazy creation of the font because we need to match whatever
  673. // font the listview control is using and we can't tell which font
  674. // that is until we actually have the HDC for the listbox.
  675. LOGFONT lf;
  676. HFONT hfont = (HFONT)GetCurrentObject(lplvcd->nmcd.hdc, OBJ_FONT);
  677. GetObject(hfont, sizeof(LOGFONT), &lf);
  678. lf.lfWeight += FW_BOLD-FW_NORMAL;
  679. g_hfontBold = CreateFontIndirect(&lf);
  680. }
  681. if (g_hfontBold)
  682. {
  683. SelectObject(lplvcd->nmcd.hdc, g_hfontBold);
  684. SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NEWFONT);
  685. return CDRF_NEWFONT;
  686. }
  687. }
  688. SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_DODEFAULT);
  689. return CDRF_DODEFAULT;
  690. }
  691. return 0;
  692. #undef lplvcd
  693. case LVN_COLUMNCLICK:
  694. m_iSortCol = pnmlv->iSubItem;
  695. ListView_SortItems( pnmhdr->hwndFrom, Dialing_ListSort, m_iSortCol);
  696. break;
  697. case LVN_GETEMPTYTEXT:
  698. #define pnmlvi (((NMLVDISPINFO *)pnmhdr)->item)
  699. LoadString(GetUIInstance(), IDS_CLICKNEW, pnmlvi.pszText, pnmlvi.cchTextMax);
  700. SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,TRUE);
  701. #undef pnmlvi
  702. break;
  703. default:
  704. break;
  705. }
  706. #undef pnmlv
  707. break;
  708. default:
  709. switch (pnmhdr->code)
  710. {
  711. case PSN_APPLY:
  712. // TODO: Ensure that a location is selected in the list
  713. m_locs.SaveToRegistry();
  714. break;
  715. }
  716. return 0;
  717. }
  718. return 1;
  719. }
  720. // ********************************************************************
  721. //
  722. // Advanced Property Page functions (formerly Telephony Drivers page)
  723. //
  724. // ********************************************************************
  725. #include "drv.h"
  726. INT_PTR CALLBACK CDialingRulesPropSheet::Advanced_DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  727. {
  728. CDialingRulesPropSheet* pthis = (CDialingRulesPropSheet*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  729. switch(uMsg)
  730. {
  731. case WM_INITDIALOG:
  732. pthis = (CDialingRulesPropSheet*)(((PROPSHEETPAGE*)lParam)->lParam);
  733. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pthis);
  734. return pthis->Advanced_OnInitDialog(hwndDlg);
  735. case WM_COMMAND:
  736. return pthis->Advanced_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam );
  737. case WM_HELP:
  738. // Process clicks on controls after Context Help mode selected
  739. WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a113HelpIDs);
  740. break;
  741. case WM_CONTEXTMENU:
  742. // Process right-clicks on controls
  743. WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a113HelpIDs);
  744. break;
  745. }
  746. return 0;
  747. }
  748. BOOL CDialingRulesPropSheet::Advanced_OnInitDialog(HWND hDlg)
  749. {
  750. UINT uUpdated;
  751. if ( !FillDriverList(GetDlgItem(hDlg, IDC_LIST)) )
  752. {
  753. EndDialog(hDlg, IDCANCEL);
  754. return FALSE;
  755. }
  756. // DWLP_USER is used to store state information about wheter we have disabled
  757. // the property sheet's cancel button. For starters we have not done this.
  758. SetWindowLong( hDlg, DWLP_USER, FALSE );
  759. UpdateDriverDlgButtons (hDlg);
  760. return TRUE;
  761. }
  762. BOOL CDialingRulesPropSheet::Advanced_OnCommand(HWND hwndParent, int wID, int wNotifyCode, HWND hwndCrl)
  763. {
  764. switch (wID)
  765. {
  766. case IDC_ADD:
  767. // add a new driver
  768. if ( IDOK == DialogBoxParam(
  769. GetUIInstance(),
  770. MAKEINTRESOURCE( IDD_ADD_DRIVER ),
  771. hwndParent,
  772. AddDriver_DialogProc,
  773. 0 ) )
  774. {
  775. FillDriverList(GetDlgItem(hwndParent, IDC_LIST));
  776. if (SetWindowLong(hwndParent, DWLP_USER, TRUE) == FALSE)
  777. {
  778. // We have performed a non-cancelable action, update the property sheet to reflect this
  779. PropSheet_CancelToClose( GetParent( hwndParent ) );
  780. }
  781. UpdateDriverDlgButtons(hwndParent);
  782. } // end if
  783. break;
  784. case IDC_LIST:
  785. if ( LBN_SELCHANGE == wNotifyCode )
  786. {
  787. UpdateDriverDlgButtons(hwndParent);
  788. break;
  789. }
  790. else if ( LBN_DBLCLK != wNotifyCode || !IsWindowEnabled( GetDlgItem( hwndParent, IDC_EDIT ) ))
  791. {
  792. // we only fall through if the user double clicked on an editable item
  793. break;
  794. }
  795. // fall through
  796. case IDC_EDIT:
  797. if ( SetupDriver(hwndParent, GetDlgItem(hwndParent, IDC_LIST)) )
  798. {
  799. if ( SetWindowLong( hwndParent, DWLP_USER, TRUE ) == FALSE ) // modified
  800. {
  801. PropSheet_CancelToClose( GetParent(hwndParent) );
  802. }
  803. }
  804. break;
  805. case IDC_REMOVE:
  806. {
  807. TCHAR szCaption[MAX_INPUT];
  808. TCHAR szMessage[512];
  809. LoadString(GetUIInstance(), IDS_REMOVEPROVIDER, szCaption, ARRAYSIZE(szCaption));
  810. LoadString(GetUIInstance(), IDS_CONFIRM_DRIVER_REMOVE, szMessage, ARRAYSIZE(szMessage));
  811. MessageBeep( MB_ICONASTERISK );
  812. if ( IDYES == MessageBox(hwndParent, szMessage, szCaption, MB_YESNO | MB_DEFBUTTON2) )
  813. {
  814. if (SetWindowLong (hwndParent, DWLP_USER, TRUE) == FALSE) // modified
  815. {
  816. PropSheet_CancelToClose( GetParent( hwndParent ) );
  817. }
  818. RemoveSelectedDriver( hwndParent, GetDlgItem(hwndParent, IDC_LIST) );
  819. UpdateDriverDlgButtons (hwndParent);
  820. }
  821. }
  822. break;
  823. }
  824. return 1;
  825. }
  826. HINSTANCE GetUIInstance()
  827. {
  828. if ( NULL == g_hInstUI )
  829. {
  830. g_hInstUI = LoadLibrary(TEXT("tapiui.dll"));
  831. // g_hInstUI = GetModuleHandle(TEXT("tapi32.dll"));
  832. }
  833. return g_hInstUI;
  834. }
  835. LONG EnsureOneLocation (HWND hwnd)
  836. {
  837. CLocations locs;
  838. locs.Initialize();
  839. // If there are no locations, launch the simple location dialog
  840. if ( 0 == locs.GetNumLocations() )
  841. {
  842. // if we are in lineTranslateDialog mode, then we display the simple
  843. int iRes;
  844. iRes = (int)DialogBoxParam(GetUIInstance(), MAKEINTRESOURCE(IDD_SIMPLELOCATION),hwnd,
  845. LocWizardDlgProc, (LPARAM)TAPI_VERSION2_2);
  846. if ( IDOK == iRes )
  847. {
  848. // now we need to re-initalize to pick up the new location
  849. locs.Initialize();
  850. // Now we need to figure out the ID of the location we just created
  851. CLocation * pLoc;
  852. locs.Reset();
  853. if ( S_OK == locs.Next( 1, &pLoc, NULL ) )
  854. {
  855. // Set this ID as the default location
  856. locs.SetCurrentLocationID(pLoc->GetLocationID());
  857. CountryRunOnce();
  858. }
  859. // we've already made a commited change, so save the result
  860. locs.SaveToRegistry();
  861. }
  862. else
  863. {
  864. return LINEERR_USERCANCELLED;
  865. }
  866. }
  867. return S_OK;
  868. }
  869. void CountryRunOnce()
  870. {
  871. //
  872. // This is soft modem workaround provided by unimodem team.
  873. //
  874. // 1. Some vendors set the GCI code incorrectly based on the TAPI location
  875. // key (which is a bad thing L)
  876. // 2. Some modems do not conform to GCI
  877. // 3. Some modems do not correctly accept AT+GCI commands.
  878. // (+GCI is Modems AT commands for setting country)
  879. //
  880. // The conformance check ensures the GCI value is properly sync
  881. // with the TAPI location. It disables GCI if the modem does not conform
  882. // to the GCI spec.
  883. //
  884. // This function can take as long as 15 seconds. We should make sure the UI
  885. // doesn't appear to hang during the call.
  886. //
  887. typedef void (*COUNTRYRUNONCE)();
  888. HMODULE hLib;
  889. hLib=LoadLibrary(TEXT("modemui.dll"));
  890. if (hLib != NULL)
  891. {
  892. COUNTRYRUNONCE Proc;
  893. Proc=(COUNTRYRUNONCE)GetProcAddress(hLib,"CountryRunOnce");
  894. if (Proc != NULL)
  895. {
  896. Proc();
  897. }
  898. FreeLibrary(hLib);
  899. }
  900. }