Leaked source code of windows server 2003
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.

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