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.

1267 lines
46 KiB

  1. /**********************************************************************************
  2. *
  3. * dial.c - autodialer functionality for the wab
  4. * created on 7/1/98 by t-jstaj
  5. *
  6. * Note: The reason for having this dialog in teh WAB was to integrate with
  7. * the NT TAPI team .. we tried using TAPI3.0 which is debuting in
  8. * NT5 but found it too unstable, subject to change, and hard to include
  9. * in our standard headers .. hence the NT5_TAPI3.0 support is currently
  10. * #ifdefed out _NT50_TAPI30 .. if you reenable that support you should
  11. * test it since we havent been able to test the code much - vikramm
  12. **********************************************************************************/
  13. #include "_apipch.h"
  14. #define MAX_PHONE_NUMS 10
  15. #define MAX_PHONE_LEN 32
  16. static DWORD rgDLDialHelpIDs[] =
  17. {
  18. // these are dummy for now, need to change at some point
  19. IDC_NEWCALL_STATIC_CONTACT, IDH_WAB_DIALER_CONTACT,
  20. IDC_NEWCALL_COMBO_CONTACT, IDH_WAB_DIALER_CONTACT,
  21. IDC_NEWCALL_STATIC_PHNUM, IDH_WAB_DIALER_PHONE,
  22. IDC_NEWCALL_COMBO_PHNUM, IDH_WAB_DIALER_PHONE,
  23. IDC_NEWCALL_BUTTON_CALL, IDH_WAB_DIALER_CALL,
  24. IDC_NEWCALL_BUTTON_PROPERTIES, IDH_WAB_DIALER_PROPERTIES,
  25. IDC_NEWCALL_BUTTON_DIALPROP, IDH_WAB_DIALING_PROPERTIES,
  26. IDC_NEWCALL_GROUP_DIALNUM, IDH_WAB_COMM_GROUPBOX,
  27. IDC_NEWCALL_BUTTON_CLOSE, IDH_WAB_FIND_CLOSE,
  28. 0,0
  29. };
  30. // prototypes
  31. #ifdef _NT50_TAPI30
  32. HRESULT HrLPSZToBSTR(LPTSTR lpsz, BSTR *pbstr);
  33. #endif //#ifdef _NT50_TAPI30
  34. HRESULT HrConfigDialog( HWND );
  35. UINT GetPhoneNumData( HWND , LPTSTR );
  36. BOOL RetrieveData( HWND, LPTSTR szDestAddr, LPTSTR szAppName,
  37. LPTSTR szCalledParty, LPTSTR szComment);
  38. HRESULT HrSetComboText( HWND );
  39. void SetNumbers( HWND, LPSBinary );
  40. INT_PTR CALLBACK ShowNewCallDlg(HWND, UINT, WPARAM, LPARAM);
  41. LONG HrStartCall(LPTSTR, LPTSTR, LPTSTR, LPTSTR);
  42. void UpdateNewCall(HWND, BOOL);
  43. void DisableCallBtnOnEmptyPhoneField(HWND);
  44. HRESULT HrInitDialog(HWND);
  45. HRESULT HrCallButtonActivate( HWND );
  46. HRESULT HrPropButtonActivate( HWND );
  47. HRESULT HrCloseBtnActivate ( HWND );
  48. VOID FAR PASCAL lineCallbackFunc( DWORD, DWORD, DWORD_PTR, DWORD_PTR, DWORD_PTR, DWORD_PTR);
  49. BOOL fContextExtCoinitForDial = FALSE;
  50. typedef struct _IABSB
  51. {
  52. LPADRBOOK lpIAB;
  53. LPSBinary lpSB;
  54. } IABSB, * LPIABSB;
  55. /**
  56. HrExecDialog: entry point to Dialer Dialog
  57. [IN] hWndLV - handle to the WAB's ListView
  58. [IN] lpAdrBook - pointer to the IAdrBook object
  59. */
  60. HRESULT HrExecDialDlg(HWND hWndLV, LPADRBOOK lpAdrBook )
  61. {
  62. HRESULT hr = E_FAIL;
  63. LPRECIPIENT_INFO lpItem = NULL;
  64. LPSPropValue lpPropArray = NULL;
  65. ULONG ulcProps = 0;
  66. UINT iItemIndex;
  67. LPSBinary lpSB = NULL;
  68. IABSB ptr_store;
  69. int rVal, nCount = ListView_GetSelectedCount(hWndLV);
  70. TCHAR szBuf[MAX_PATH*2];
  71. ptr_store.lpIAB = lpAdrBook;
  72. ptr_store.lpSB = NULL;
  73. if( !lpAdrBook )
  74. DebugTrace(TEXT("lpAdrbook is null in ExecDialDlg\n"));
  75. if(nCount == 1)
  76. {
  77. iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
  78. lpItem = GetItemFromLV(hWndLV, iItemIndex);
  79. if(lpItem && lpItem->cbEntryID != 0)
  80. {
  81. ListView_GetItemText( hWndLV, iItemIndex, 0, szBuf, CharSizeOf( szBuf ));
  82. // what does this allocate space for SBinary
  83. MAPIAllocateBuffer( sizeof(SBinary), (LPVOID *) &lpSB);
  84. if( lpSB )
  85. {
  86. // allocate more space for lpb
  87. MAPIAllocateMore(lpItem->cbEntryID, lpSB, (LPVOID *) &(lpSB->lpb) );
  88. }
  89. if( !lpSB->lpb)
  90. {
  91. MAPIFreeBuffer(lpSB);
  92. goto out;
  93. }
  94. CopyMemory(lpSB->lpb, lpItem->lpEntryID, lpItem->cbEntryID);
  95. lpSB->cb = lpItem->cbEntryID;
  96. ptr_store.lpSB = lpSB;
  97. }
  98. else
  99. {
  100. DebugTrace(TEXT("Bad WAB info will not display\n"));
  101. goto out;
  102. }
  103. }
  104. // display the dialog box to prompt user to make call
  105. if(!DialogBoxParam(hinstMapiX, MAKEINTRESOURCE(IDD_NEWCALL),
  106. GetParent(hWndLV), ShowNewCallDlg, (LPARAM)&ptr_store) )
  107. {
  108. hr = S_OK;
  109. }
  110. else
  111. {
  112. DebugTrace(TEXT("Dialer dialog creation failed:%d\n"), GetLastError());
  113. }
  114. out:
  115. if(lpPropArray)
  116. MAPIFreeBuffer(lpPropArray);
  117. if( lpSB )
  118. MAPIFreeBuffer(lpSB);
  119. return hr;
  120. }
  121. /**
  122. ShowNewCallDlg: process events
  123. */
  124. INT_PTR CALLBACK ShowNewCallDlg(HWND hDlg,
  125. UINT uMsg,
  126. WPARAM wParam,
  127. LPARAM lParam)
  128. {
  129. switch (uMsg)
  130. {
  131. case WM_INITDIALOG:
  132. {
  133. HRESULT hr;
  134. SetWindowLongPtr( hDlg, DWLP_USER, lParam );
  135. hr = HrInitDialog(hDlg);
  136. // [PaulHi] 12/3/98 Raid #56045
  137. // Set up child window fonts with default GUI font
  138. EnumChildWindows(hDlg, SetChildDefaultGUIFont, (LPARAM) 0);
  139. return HR_FAILED( hr );
  140. }
  141. case WM_COMMAND:
  142. switch (LOWORD(wParam) )
  143. {
  144. case IDC_NEWCALL_COMBO_CONTACT:
  145. /** only want to make a change if the user actually chooses a new contact
  146. */
  147. if( HIWORD(wParam) == CBN_SELENDOK )
  148. {
  149. HRESULT hr;
  150. UpdateNewCall(hDlg, TRUE);
  151. hr = HrSetComboText( GetDlgItem(hDlg, IDC_NEWCALL_COMBO_PHNUM) );
  152. if( HR_FAILED( hr ) )
  153. {
  154. DebugTrace(TEXT("unable to set text\n"));
  155. SendMessage(hDlg, IDCANCEL, 0, 0);
  156. }
  157. }
  158. return FALSE;
  159. case IDC_NEWCALL_COMBO_PHNUM:
  160. // want to set the text of the selected item when the box closes
  161. if( HIWORD(wParam) == CBN_CLOSEUP )
  162. {
  163. HRESULT hr = HrSetComboText( GetDlgItem(hDlg, IDC_NEWCALL_COMBO_PHNUM) );
  164. if( HR_FAILED( hr ) )
  165. {
  166. DebugTrace(TEXT("unable to set text in PHNUM closeup or selchange\n"));
  167. SendMessage(hDlg, IDCANCEL, 0, 0);
  168. }
  169. return FALSE;
  170. }
  171. // reset all the values of the combobox before display since they
  172. // were altered from the last time a selection was made.
  173. else if( HIWORD(wParam) == CBN_DROPDOWN )
  174. {
  175. UpdateNewCall(hDlg, FALSE);
  176. }
  177. else if (HIWORD(wParam) == CBN_EDITUPDATE )
  178. {
  179. DisableCallBtnOnEmptyPhoneField(hDlg);
  180. }
  181. else if ( HIWORD(wParam) == CBN_SELCHANGE )
  182. {
  183. if( !SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM, CB_GETDROPPEDSTATE, (WPARAM)(0), (LPARAM)(0) ) )
  184. {
  185. HRESULT hr = HrSetComboText( GetDlgItem(hDlg, IDC_NEWCALL_COMBO_PHNUM) );
  186. if( HR_FAILED( hr ) )
  187. {
  188. DebugTrace(TEXT("unable to set text in PHNUM closeup or selchange\n"));
  189. SendMessage(hDlg, IDCANCEL, 0, 0);
  190. }
  191. return FALSE;
  192. }
  193. }
  194. return FALSE;
  195. case IDC_NEWCALL_BUTTON_DIALPROP:
  196. {
  197. HRESULT hr = HrConfigDialog( hDlg );
  198. if( HR_FAILED(hr) )
  199. {
  200. DebugTrace(TEXT("config dlg failed"));
  201. DebugTrace(TEXT(" error was %x\n"), HRESULT_CODE(hr));
  202. SendMessage(hDlg, IDCANCEL, 0, 0);
  203. }
  204. return FALSE;
  205. }
  206. case IDC_NEWCALL_BUTTON_CALL:
  207. {
  208. HRESULT hr = HrCallButtonActivate( hDlg );
  209. if( HR_FAILED(hr) )
  210. {
  211. DebugTrace(TEXT("Unable to make call\n"));
  212. SendMessage( hDlg, IDCANCEL, (WPARAM)(0), (LPARAM)(0) );
  213. }
  214. }
  215. return FALSE;
  216. case IDC_NEWCALL_BUTTON_PROPERTIES:
  217. {
  218. HRESULT hr = HrPropButtonActivate( hDlg );
  219. if( HR_FAILED(hr) )
  220. {
  221. DebugTrace(TEXT("Unable to show properties\n"));
  222. SendMessage( hDlg, IDCANCEL, (WPARAM)(0), (LPARAM)(0) );
  223. }
  224. return FALSE;
  225. }
  226. case IDCANCEL:
  227. case IDC_NEWCALL_BUTTON_CLOSE:
  228. {
  229. HRESULT hr = HrCloseBtnActivate(hDlg);
  230. return FALSE;
  231. }
  232. default:
  233. return TRUE;
  234. }
  235. case WM_HELP:
  236. WABWinHelp(((LPHELPINFO)lParam)->hItemHandle,
  237. g_szWABHelpFileName,
  238. HELP_WM_HELP,
  239. (DWORD_PTR)(LPSTR) rgDLDialHelpIDs );
  240. break;
  241. }
  242. return FALSE;
  243. }
  244. /**
  245. HrInitDialog: initializes the dialer dialog
  246. */
  247. HRESULT HrInitDialog( HWND hDlg )
  248. {
  249. HRESULT hr = E_FAIL, hr2;
  250. HWND hComboContact = GetDlgItem( hDlg, IDC_NEWCALL_COMBO_CONTACT);
  251. ULONG lpcbEID, ulObjType = 0, ulResult;
  252. LPENTRYID lpEID = NULL;
  253. LPMAPITABLE lpAB = NULL;
  254. LPSRowSet lpRow = NULL;
  255. LPSRowSet lpRowAB = NULL;
  256. LPABCONT lpContainer = NULL;
  257. UINT cNumRows = 0;
  258. UINT nRows = 0;
  259. UINT i, cEntries = 0;
  260. LPSBinary tVal;
  261. LPIABSB lpPtrStore = (LPIABSB)GetWindowLongPtr( hDlg, DWLP_USER );
  262. LPADRBOOK lpAdrBook = lpPtrStore->lpIAB;
  263. AssertSz( (lpAdrBook != NULL), TEXT("lpAdrBook is NULL in shownewcall!\n"));
  264. hr = (HRESULT) SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM, EM_SETLIMITTEXT, (WPARAM)(TAPIMAXDESTADDRESSSIZE), (LPARAM)(0) );
  265. if( HR_FAILED(hr) )
  266. {
  267. DebugTrace(TEXT("unable to set text len in PHNUM\n"));
  268. }
  269. // get the default Container
  270. hr = lpAdrBook->lpVtbl->GetPAB(lpAdrBook, &lpcbEID, &lpEID);
  271. if( HR_FAILED(hr) )
  272. {
  273. DebugTrace(TEXT("Unable to get PAB\n"));
  274. goto cleanup;
  275. }
  276. // open the entry
  277. hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  278. lpcbEID,
  279. (LPENTRYID)lpEID,
  280. NULL,
  281. 0,
  282. &ulObjType,
  283. (LPUNKNOWN *)&lpContainer);
  284. MAPIFreeBuffer(lpEID);
  285. lpEID = NULL;
  286. if( HR_FAILED(hr) )
  287. {
  288. DebugTrace(TEXT("Unable to open contents\n"));
  289. goto cleanup;
  290. }
  291. // get the contents
  292. hr = lpContainer->lpVtbl->GetContentsTable(lpContainer,
  293. MAPI_UNICODE | WAB_PROFILE_CONTENTS | WAB_CONTENTTABLE_NODATA,
  294. &lpAB );
  295. if( HR_FAILED(hr) )
  296. {
  297. DebugTrace(TEXT("Unable to get contents table\n"));
  298. goto cleanup;
  299. }
  300. // order the columns in the Table
  301. // order will be displayname, entryid
  302. // table MUST set columns in order requested
  303. hr = lpAB->lpVtbl->SetColumns( lpAB, (LPSPropTagArray)&irnColumns, 0);
  304. if( HR_FAILED(hr) )
  305. {
  306. DebugTrace(TEXT("Unable to set contents table\n"));
  307. goto cleanup;
  308. }
  309. hr = lpAB->lpVtbl->SeekRow(lpAB, BOOKMARK_BEGINNING, 0, NULL);
  310. if( HR_FAILED(hr) )
  311. {
  312. DebugTrace(TEXT("Unable to seekRow \n"));
  313. goto cleanup;
  314. }
  315. do{
  316. //loop over all the info in the selected rows
  317. hr = lpAB->lpVtbl->QueryRows(lpAB, 1, 0, &lpRowAB);
  318. if( HR_FAILED(hr) )
  319. {
  320. DebugTrace(TEXT("Unable to Query Rows\n"));
  321. goto cleanup;
  322. }
  323. cNumRows = lpRowAB->cRows;
  324. if( lpRowAB && cNumRows > 0) // temp fix to check for cNumRows
  325. {
  326. UINT recentIndex;
  327. // store the name
  328. LPTSTR lpsz = lpRowAB->aRow[0].lpProps[irnPR_DISPLAY_NAME].Value.LPSZ;
  329. // store the entryID info
  330. LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[irnPR_ENTRYID].Value.bin.lpb;
  331. ULONG cbEID = lpRowAB->aRow[0].lpProps[irnPR_ENTRYID].Value.bin.cb;
  332. LPSBinary lpSB = NULL;
  333. // we can ignore non mail-users for our purposes
  334. // since they won't have ph numbers
  335. // will add strings to the combo box, and will associate the entryid with
  336. // each entry with its entryID so that it will be easy to obtain the other entry fields
  337. // what does this allocate space for SBinary
  338. MAPIAllocateBuffer( sizeof(SBinary), (LPVOID *) &lpSB);
  339. if( lpSB )
  340. {
  341. // allocate more space for lpb
  342. MAPIAllocateMore(cbEID, lpSB, (LPVOID *) &(lpSB->lpb) );
  343. }
  344. if( !lpSB->lpb)
  345. {
  346. // because of memmangement in WAB this will free all
  347. // the mem in SBinary( deep free )
  348. MAPIFreeBuffer(lpSB);
  349. continue;
  350. }
  351. CopyMemory(lpSB->lpb, lpEID, cbEID);
  352. lpSB->cb = cbEID;
  353. // next entry, list is sorted
  354. recentIndex = (UINT) SendMessage( hComboContact, CB_ADDSTRING, (WPARAM)(0),
  355. (LPARAM)(lpsz) );
  356. // set the data as the pointer to entryid info for the item at that index
  357. SendMessage( hComboContact, CB_SETITEMDATA,
  358. (WPARAM)(recentIndex), (LPARAM)(lpSB));
  359. cEntries++;
  360. }
  361. FreeProws(lpRowAB);
  362. }while( SUCCEEDED(hr) && cNumRows && lpRowAB );
  363. if( (LPVOID)lpPtrStore->lpSB )
  364. {
  365. for( i = 0; i < cEntries; i++)
  366. {
  367. tVal = (LPSBinary)(PULONG)SendMessage( hComboContact, CB_GETITEMDATA,
  368. (WPARAM)(i), (LPARAM)(0) );
  369. if( tVal && tVal->cb && tVal->cb == lpPtrStore->lpSB->cb )
  370. {
  371. if( memcmp((LPVOID)tVal->lpb,
  372. (LPVOID)lpPtrStore->lpSB->lpb, (size_t)tVal->cb) == 0)
  373. {
  374. SendMessage(hComboContact, CB_SETCURSEL,
  375. (WPARAM)(i), (LPARAM)(0) );
  376. break;
  377. }
  378. }
  379. }
  380. }
  381. else
  382. SendMessage(hComboContact, CB_SETCURSEL, (WPARAM)(0), (LPARAM)(0) );
  383. cleanup:
  384. if( lpContainer )
  385. lpContainer->lpVtbl->Release(lpContainer);
  386. if( lpAB)
  387. lpAB->lpVtbl->Release(lpAB);
  388. UpdateNewCall(hDlg, TRUE);
  389. hr2 = HrSetComboText( GetDlgItem(hDlg, IDC_NEWCALL_COMBO_PHNUM) );
  390. DisableCallBtnOnEmptyPhoneField(hDlg);
  391. if( HR_SUCCEEDED(hr) && HR_FAILED(hr2))
  392. return hr2;
  393. return hr;
  394. }
  395. /**
  396. HrCallButtonActivate: initiates the dialing procedures for the dialer Dlg
  397. */
  398. HRESULT HrCallButtonActivate( HWND hDlg )
  399. {
  400. HRESULT hr = E_FAIL;
  401. TCHAR szDestAddr[TAPIMAXDESTADDRESSSIZE];
  402. TCHAR szAppName[TAPIMAXAPPNAMESIZE];
  403. TCHAR szCalledParty[TAPIMAXCALLEDPARTYSIZE];
  404. TCHAR szComment[TAPIMAXCOMMENTSIZE];
  405. BOOL fGotNum = RetrieveData( hDlg, szDestAddr, szAppName, szCalledParty, szComment);
  406. if( !fGotNum )
  407. {
  408. ShowMessageBox( hDlg, idsNoDialerDataMsg, MB_OK | MB_ICONEXCLAMATION );
  409. }
  410. else
  411. {
  412. hr = HrStartCall(szDestAddr, szAppName, szCalledParty, szComment);
  413. /** make call spawns it's own thread so hr only reflects
  414. whether or not it was able to find the phone device and
  415. initiate the calling sequence, not the status of the call.
  416. */
  417. }
  418. return hr;
  419. }
  420. /**
  421. HrPropButtonActivate: displays the properties for the selected contact in the dialer Dlg
  422. */
  423. HRESULT HrPropButtonActivate( HWND hDlg )
  424. {
  425. HRESULT hr = E_FAIL;
  426. LONG iCurContactSel;
  427. LPIABSB lpPtrStore = (LPIABSB)GetWindowLongPtr( hDlg, DWLP_USER );
  428. LPADRBOOK lpAdrBook = lpPtrStore->lpIAB;
  429. AssertSz((lpAdrBook != NULL), TEXT("lpAdrBook is NULL in SetNumbers\n"));
  430. // first get the cached data for the contact currently selected
  431. iCurContactSel = (LONG) SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_CONTACT,
  432. CB_GETCURSEL,(WPARAM)(0), (LPARAM)(0));
  433. // if something is selected
  434. if( iCurContactSel >= 0 )
  435. {
  436. LRESULT lpdata = SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_CONTACT,
  437. CB_GETITEMDATA, (WPARAM)(iCurContactSel), (LPARAM)(LPTSTR)(0));
  438. // if we have a specially cached entryid ..
  439. //
  440. if( lpdata != CB_ERR && ((LPSBinary)lpdata)->cb && ((LPSBinary)lpdata)->lpb)
  441. {
  442. LPSBinary lpSB = (LPSBinary)lpdata;
  443. hr = lpAdrBook->lpVtbl->Details(lpAdrBook, (PULONG_PTR) &hDlg,
  444. NULL, NULL,
  445. lpSB->cb,
  446. (LPENTRYID) lpSB->lpb,
  447. NULL, NULL,
  448. NULL, 0);
  449. }
  450. }
  451. return hr;
  452. }
  453. /**
  454. HrCloseBtnActivate: Handles freeing memory from the combo boxes
  455. */
  456. HRESULT HrCloseBtnActivate( HWND hDlg )
  457. {
  458. HRESULT hr = S_OK;
  459. UINT i, nComboSize;
  460. PULONG nData;
  461. LPTSTR lpData;
  462. HWND hComboItem = GetDlgItem (hDlg, IDC_NEWCALL_COMBO_CONTACT);
  463. // loop through all the items in the box and free the address pointed
  464. // to by the data item
  465. nComboSize = (UINT) SendMessage( hComboItem, CB_GETCOUNT, (WPARAM) (0), (LPARAM) (0) );
  466. for( i = 0; i < nComboSize; i++)
  467. {
  468. nData = (PULONG)SendMessage(hComboItem, CB_GETITEMDATA, (WPARAM)(i), (LPARAM)(0) );
  469. if ((LRESULT)nData != CB_ERR && nData != NULL)
  470. {
  471. if( nData )
  472. MAPIFreeBuffer( (LPSBinary)nData );
  473. }
  474. else
  475. hr = E_FAIL;
  476. }
  477. SendMessage( hComboItem, CB_RESETCONTENT, (WPARAM)(0), (LPARAM)(0));
  478. hComboItem = GetDlgItem( hDlg, IDC_NEWCALL_COMBO_PHNUM);
  479. nComboSize = (UINT) SendMessage( hComboItem, CB_GETCOUNT, (WPARAM)(0), (LPARAM)(0) );
  480. for(i = 0; i < nComboSize; i++)
  481. {
  482. lpData = (LPTSTR)SendMessage(hComboItem, CB_GETITEMDATA, (WPARAM)(i), (LPARAM)(0) );
  483. if( (LRESULT)lpData != CB_ERR && lpData != NULL )
  484. {
  485. if( lpData )
  486. LocalFree( lpData );
  487. }
  488. else
  489. hr = E_FAIL;
  490. }
  491. // SendMessage( hComboItem, CB_RESETCONTENT, (WPARAM)(0), (LPARAM)(0));
  492. EndDialog(hDlg, HR_SUCCEEDED(hr) );
  493. return hr;
  494. }
  495. /**
  496. HrStartCall: handles the TAPI calls required to dial a telephone number
  497. [IN] szDestAddr - the destination telephone number to call
  498. [IN] szAppName - (not used) the application to use in the dialing procedure
  499. [IN] szCalledParty - the name of the person called (will be displayed by the TAPI UI)
  500. [IN] szComment - (not used) a comment associated with this number
  501. */
  502. HRESULT HrStartCall(LPTSTR szDestAddr, LPTSTR szAppName, LPTSTR szCalledParty, LPTSTR szComment)
  503. {
  504. typedef LONG (CALLBACK* LPFNTAPISTARTCALL)(LPSTR,LPSTR,LPSTR,LPSTR);
  505. HINSTANCE hDLL;
  506. LPFNTAPISTARTCALL lpfnTapi; // Function pointer
  507. HRESULT lRetCode;
  508. HRESULT hr = E_FAIL;
  509. #ifdef _NT50_TAPI30
  510. ITRequest * pRequest = NULL;
  511. // begin NT5 code
  512. if( CoInitialize(NULL) == S_FALSE )
  513. CoUninitialize();
  514. else
  515. fContextExtCoinitForDial = TRUE;
  516. hr = CoCreateInstance(
  517. &CLSID_RequestMakeCall,
  518. NULL,
  519. CLSCTX_INPROC_SERVER,
  520. &IID_ITRequest,
  521. (LPVOID *)&pRequest
  522. );
  523. if( HR_SUCCEEDED(hr) )
  524. {
  525. BSTR pDestAdr, pAppName, pCalledParty, pComment;
  526. HrLPSZToBSTR(szDestAddr, &pDestAdr);
  527. HrLPSZToBSTR(szAppName, &pAppName);
  528. HrLPSZToBSTR(szCalledParty, &pCalledParty);
  529. HrLPSZToBSTR(szComment, &pComment);
  530. hr = pRequest->lpVtbl->MakeCall(pRequest, pDestAdr, pAppName, pCalledParty, pComment );
  531. DebugTrace(TEXT("COM Environment\n"));
  532. LocalFreeAndNull(&pDestAdr);
  533. LocalFreeAndNull(&pAppName);
  534. LocalFreeAndNull(&pCalledParty);
  535. LocalFreeAndNull(&pComment);
  536. if(fContextExtCoinitForDial)
  537. {
  538. CoUninitialize();
  539. fContextExtCoinitForDial = FALSE;
  540. }
  541. return hr;
  542. }
  543. else
  544. {
  545. if( hr == REGDB_E_CLASSNOTREG )
  546. {
  547. DebugTrace(TEXT("Class not registered\n"));
  548. }
  549. else if ( hr == CLASS_E_NOAGGREGATION )
  550. {
  551. DebugTrace(TEXT("Not able to create class as part of aggregate"));
  552. }
  553. else
  554. {
  555. DebugTrace(TEXT("Undetermined error = %d"), hr);
  556. }
  557. // end NT 5 code
  558. #endif // _NT50_TAPI30
  559. //start making the call using TAPI
  560. hDLL = LoadLibrary( TEXT("tapi32.dll"));
  561. if (hDLL != NULL)
  562. {
  563. lpfnTapi = (LPFNTAPISTARTCALL)GetProcAddress(hDLL,
  564. "tapiRequestMakeCall");
  565. if (!lpfnTapi)
  566. {
  567. // handle the error
  568. FreeLibrary(hDLL);
  569. DebugTrace(TEXT("getprocaddr tapirequestmakecall failed\n"));
  570. }
  571. else
  572. {
  573. // call the function
  574. // [PaulHi] 2/23/99 Raid 295116. The tapi32.dll, tapiRequestMakeCall()
  575. // function takes single byte char strings, not double byte.
  576. LPSTR pszDestAddr = ConvertWtoA(szDestAddr);
  577. LPSTR pszCalledParty = ConvertWtoA(szCalledParty);
  578. hr = lpfnTapi( pszDestAddr, NULL,
  579. pszCalledParty, NULL);
  580. if( HR_FAILED(hr) )
  581. {
  582. DebugTrace(TEXT("make call returned error of %x\n"), hr );
  583. }
  584. LocalFreeAndNull(&pszDestAddr);
  585. LocalFreeAndNull(&pszCalledParty);
  586. // free the resource
  587. FreeLibrary(hDLL);
  588. }
  589. }
  590. #ifdef _NT50_TAPI30
  591. }
  592. #endif // _NT50_TAPI30
  593. return hr;
  594. }
  595. /**
  596. UpdateNewCall: Updates the phone combo info (removing the description string)
  597. [IN] fContactChanged - indicates whether or not it is necessary to select the first
  598. entry in the PHNUM combo.
  599. */
  600. void UpdateNewCall(HWND hDlg, BOOL fContactChanged)
  601. {
  602. HWND hContactCombo = GetDlgItem( hDlg, IDC_NEWCALL_COMBO_CONTACT);
  603. LONG iCurContactSel, iCurPhSel;
  604. iCurContactSel = (LONG) SendMessage( hContactCombo, CB_GETCURSEL,(WPARAM)(0), (LPARAM)(0));
  605. // if something is selected
  606. if( iCurContactSel >= 0 )
  607. {
  608. PULONG lpdata;
  609. lpdata = (PULONG)SendMessage( hContactCombo, CB_GETITEMDATA,
  610. (WPARAM)(iCurContactSel), (LPARAM)(LPTSTR)(0));
  611. iCurPhSel = (LONG) SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM,
  612. CB_GETCURSEL, (WPARAM)(0), (LPARAM)(0) );
  613. // set the data in the combo boxes
  614. AssertSz( (LRESULT)lpdata != CB_ERR, TEXT("No data cached for this entry\n") );
  615. SetNumbers( hDlg, (LPSBinary)lpdata );
  616. if( iCurPhSel < 0 || fContactChanged) iCurPhSel = 0;
  617. SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM, CB_SETCURSEL, (WPARAM)(iCurPhSel), (LPARAM)(0));
  618. }
  619. DisableCallBtnOnEmptyPhoneField(hDlg);
  620. }
  621. /**
  622. RetrieveData: retrieves dialing information from the NEWCALL dialog,
  623. memory must have been allocated for the character buffers
  624. [OUT] szDestAddr - the phone number to call, retrieved from the PHNUM combo
  625. [OUT] szAppName - (not used) empty string returned
  626. [OUT] szCalledParty - the contact to call, retrieved from the CONTACT combo
  627. [OUT] szComment - (not used) empty string returned
  628. returns TRUE if success, FALSE if failure
  629. */
  630. BOOL RetrieveData( HWND hDlg, LPTSTR szDestAddr, LPTSTR szAppName,
  631. LPTSTR szCalledParty, LPTSTR szComment)
  632. {
  633. LPARAM cchGetText;
  634. // get the Contact name data
  635. cchGetText = SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_CONTACT, WM_GETTEXT,
  636. (WPARAM)(TAPIMAXCALLEDPARTYSIZE), (LPARAM)(LPTSTR)(szCalledParty));
  637. // store a default string in case there is no Party Name;
  638. if( cchGetText == 0 )
  639. lstrcpy(szCalledParty, TEXT("No Contact Name"));
  640. //get the Phone number data
  641. cchGetText = GetPhoneNumData( hDlg, szDestAddr );
  642. lstrcpy(szAppName,szEmpty);
  643. lstrcpy(szComment,szEmpty);
  644. // return whether or not there was a phone number to dial
  645. return ( cchGetText > 0 );
  646. }
  647. /**
  648. HrConfigDialog: initiates the dialog to change phone settings
  649. */
  650. HRESULT HrConfigDialog( HWND hWnd )
  651. {
  652. typedef LONG(CALLBACK* LPFNTAPIPHCONFIG)(HLINEAPP, DWORD, DWORD, HWND, LPTSTR);
  653. // typedef LONG(CALLBACK* LPFNTAPILINEINIT)(LPHLINEAPP, HINSTANCE, LINECALLBACK,
  654. // LPTSTR, LPDWORD, LPDWORD, LPLINEINITIALIZEEXPARAMS);
  655. typedef LONG(CALLBACK* LPFNTAPILINEINIT)(LPHLINEAPP, HINSTANCE, LINECALLBACK, LPTSTR, LPDWORD);
  656. typedef LONG(CALLBACK* LPFNTAPILINESHUTDOWN)(HLINEAPP);
  657. HLINEAPP hLineApp = 0;
  658. HINSTANCE hDLL;
  659. LPFNTAPIPHCONFIG lpfnConfig; // Function pointer
  660. LPFNTAPILINEINIT lpfnLineInit;
  661. LPFNTAPILINESHUTDOWN lpfnLineShutdown;
  662. LONG lRetCode;
  663. DWORD dwDeviceID = 0X0;
  664. DWORD dwAPIVersion = 0X00010004;
  665. LPTSTR lpszDeviceClass = NULL;
  666. //start config
  667. HRESULT hr = E_FAIL;
  668. hDLL = LoadLibrary( TEXT("tapi32.dll"));
  669. if (!hDLL )
  670. {
  671. DebugTrace(TEXT("loading tapi32.lib failed\n"));
  672. return hr;
  673. }
  674. lpfnConfig = (LPFNTAPIPHCONFIG)GetProcAddress(hDLL,
  675. "lineTranslateDialog");
  676. if (!lpfnConfig )
  677. {
  678. // handle the error
  679. DebugTrace(TEXT("getprocaddr phoneConfigDialog failed\n"));
  680. DebugTrace(TEXT("last error was %x\n"), GetLastError() );
  681. }
  682. else
  683. {
  684. lRetCode = lpfnConfig( 0, dwDeviceID, dwAPIVersion,
  685. hWnd, lpszDeviceClass);
  686. switch( lRetCode )
  687. {
  688. hr = HRESULT_FROM_WIN32(lRetCode);
  689. case 0:
  690. hr = S_OK;
  691. break;
  692. #ifdef DEBUG
  693. case LINEERR_REINIT:
  694. DebugTrace(TEXT("reeinitialize\n"));
  695. break;
  696. case LINEERR_INVALAPPNAME:
  697. DebugTrace(TEXT("invalid app name\n"));
  698. break;
  699. case LINEERR_BADDEVICEID:
  700. DebugTrace(TEXT("bad device id\n"));
  701. break;
  702. case LINEERR_INVALPARAM:
  703. DebugTrace(TEXT("invalid param\n"));
  704. break;
  705. case LINEERR_INCOMPATIBLEAPIVERSION:
  706. DebugTrace(TEXT("incompatible api ver\n"));
  707. break;
  708. case LINEERR_INVALPOINTER:
  709. DebugTrace(TEXT("invalid ptr\n"));
  710. break;
  711. case LINEERR_INIFILECORRUPT:
  712. DebugTrace(TEXT("ini file corrupt\n"));
  713. break;
  714. case LINEERR_NODRIVER:
  715. DebugTrace(TEXT("no driver\n"));
  716. break;
  717. case LINEERR_INUSE:
  718. DebugTrace(TEXT("in use\n"));
  719. break;
  720. case LINEERR_NOMEM:
  721. DebugTrace(TEXT("no mem\n"));
  722. break;
  723. case LINEERR_INVALADDRESS:
  724. DebugTrace(TEXT("invalid address\n"));
  725. break;
  726. case LINEERR_INVALAPPHANDLE:
  727. DebugTrace(TEXT("invalid phone handle\n"));
  728. break;
  729. case LINEERR_OPERATIONFAILED:
  730. DebugTrace(TEXT("op failed\n"));
  731. break;
  732. #endif // DEBUG
  733. default:
  734. DebugTrace(TEXT("(1)lpfnConfig returned a value of %x\n"), lRetCode);
  735. // this had better be Win95!!
  736. lpfnLineInit = (LPFNTAPILINEINIT)GetProcAddress(hDLL,
  737. "lineInitialize");
  738. if( !lpfnLineInit )
  739. {
  740. // handle the error
  741. DebugTrace(TEXT("getprocaddr lineInitialize failed\n"));
  742. DebugTrace(TEXT("last error was %x\n"), GetLastError() );
  743. }
  744. else
  745. {
  746. DWORD dwNumDevs = 0;
  747. // call the function
  748. lRetCode = lpfnLineInit(
  749. &hLineApp,
  750. hinstMapiX,
  751. lineCallbackFunc,
  752. NULL,
  753. &dwNumDevs);
  754. switch( lRetCode )
  755. {
  756. hr = HRESULT_FROM_WIN32(lRetCode);
  757. case 0:
  758. // shows config
  759. lRetCode = lpfnConfig( hLineApp, dwDeviceID, dwAPIVersion,
  760. hWnd, lpszDeviceClass);
  761. switch( lRetCode )
  762. {
  763. hr = HRESULT_FROM_WIN32(lRetCode);
  764. case 0:
  765. // now shutdown line
  766. lpfnLineShutdown = (LPFNTAPILINESHUTDOWN)GetProcAddress(hDLL,
  767. "lineShutdown");
  768. if( lpfnLineShutdown)
  769. {
  770. lpfnLineShutdown(hLineApp);
  771. }
  772. hr = S_OK;
  773. break;
  774. default:
  775. DebugTrace(TEXT("(2)lpfnConfig returned a value of %x\n"), lRetCode);
  776. break;
  777. }
  778. break;
  779. // end shows config
  780. #ifdef DEBUG
  781. case LINEERR_REINIT:
  782. DebugTrace(TEXT("reeinitialize\n"));
  783. break;
  784. case LINEERR_INVALAPPNAME:
  785. DebugTrace(TEXT("invalid app name\n"));
  786. break;
  787. case LINEERR_BADDEVICEID:
  788. DebugTrace(TEXT("bad device id\n"));
  789. break;
  790. case LINEERR_INVALPARAM:
  791. DebugTrace(TEXT("invalid param\n"));
  792. break;
  793. case LINEERR_INCOMPATIBLEAPIVERSION:
  794. DebugTrace(TEXT("incompatible api ver\n"));
  795. break;
  796. case LINEERR_INVALPOINTER:
  797. DebugTrace(TEXT("invalid ptr\n"));
  798. break;
  799. case LINEERR_INIFILECORRUPT:
  800. DebugTrace(TEXT("ini file corrupt\n"));
  801. break;
  802. case LINEERR_NODRIVER:
  803. DebugTrace(TEXT("no driver\n"));
  804. break;
  805. case LINEERR_INUSE:
  806. DebugTrace(TEXT("in use\n"));
  807. break;
  808. case LINEERR_NOMEM:
  809. DebugTrace(TEXT("no mem\n"));
  810. break;
  811. case LINEERR_INVALADDRESS:
  812. DebugTrace(TEXT("invalid address\n"));
  813. break;
  814. case LINEERR_INVALAPPHANDLE:
  815. DebugTrace(TEXT("invalid phone handle\n"));
  816. break;
  817. case LINEERR_OPERATIONFAILED:
  818. DebugTrace(TEXT("op failed\n"));
  819. break;
  820. #endif // DEBUG
  821. default:
  822. DebugTrace(TEXT("Initialize returned a value of %x\n"), GetLastError());
  823. break;
  824. }
  825. }
  826. }
  827. }
  828. // free the resource
  829. FreeLibrary(hDLL);
  830. return hr;
  831. }
  832. /**
  833. SetNumbers: updates the phone numbers in the PHNUM combo based on the selection
  834. in the CONTACT combo
  835. [IN] lpdata - LPSBinary that points to the data stored for the currently
  836. selected contact
  837. */
  838. void SetNumbers( HWND hWnd, LPSBinary lpdata)
  839. {
  840. ULONG ulObjType = 0;
  841. UINT i, nLen;
  842. LPMAILUSER lpMailUser = NULL;
  843. HRESULT hr;
  844. LPTSTR hData;
  845. LPIABSB lpPtrStore = (LPIABSB)GetWindowLongPtr( hWnd, DWLP_USER );
  846. LPADRBOOK lpAdrBook = lpPtrStore->lpIAB;
  847. HWND hCombo = GetDlgItem(hWnd, IDC_NEWCALL_COMBO_PHNUM);
  848. AssertSz((lpAdrBook != NULL), TEXT("lpAdrBook is NULL in SetNumbers\n"));
  849. // clear all the data in the phnum combo
  850. nLen = (UINT) SendMessage( hCombo, CB_GETCOUNT, (WPARAM)(0), (LPARAM)(0));
  851. for( i = 0; i < nLen; i++)
  852. {
  853. hData = (LPTSTR)(PULONG)SendMessage( hCombo, CB_GETITEMDATA, (WPARAM)(i), (LPARAM)(0));
  854. if( (LRESULT)hData != CB_ERR && hData != NULL)
  855. LocalFree( hData );
  856. }
  857. SendMessage( hCombo, CB_RESETCONTENT, (WPARAM)(0), (LPARAM)(0));
  858. // get the ph num
  859. hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  860. lpdata->cb,
  861. (LPENTRYID) lpdata->lpb,
  862. NULL,
  863. 0,
  864. &ulObjType,
  865. (LPUNKNOWN *)&lpMailUser);
  866. if( HR_SUCCEEDED(hr) && lpMailUser )
  867. {
  868. LPSPropValue lpPropArray;
  869. ULONG ulcValues;
  870. ULONG i;
  871. ULONG ulTempProptag;
  872. TCHAR szStr[MAX_PATH];
  873. LONG cCopied = 0;
  874. hr = lpMailUser->lpVtbl->GetProps(lpMailUser,NULL, MAPI_UNICODE, &ulcValues, &lpPropArray);
  875. if ( HR_SUCCEEDED(hr) )
  876. {
  877. for(i=0;i<ulcValues;i++)
  878. {
  879. cCopied = 0;
  880. ulTempProptag = lpPropArray[i].ulPropTag;
  881. switch( lpPropArray[i].ulPropTag )
  882. {
  883. case PR_HOME_TELEPHONE_NUMBER:
  884. cCopied = LoadString( hinstMapiX, idsPhoneLabelHome,
  885. szStr, CharSizeOf(szStr) );
  886. break;
  887. case PR_OFFICE_TELEPHONE_NUMBER:
  888. cCopied = LoadString( hinstMapiX, idsPhoneLabelBus,
  889. szStr, CharSizeOf(szStr) );
  890. break;
  891. case PR_BUSINESS2_TELEPHONE_NUMBER:
  892. cCopied = LoadString( hinstMapiX, idsPhoneLabelBus2,
  893. szStr, CharSizeOf(szStr) );
  894. break;
  895. case PR_MOBILE_TELEPHONE_NUMBER:
  896. cCopied = LoadString( hinstMapiX, idsPhoneLabelMobile,
  897. szStr, CharSizeOf(szStr) );
  898. break;
  899. case PR_RADIO_TELEPHONE_NUMBER:
  900. cCopied = LoadString( hinstMapiX, idsPhoneLabelRadio,
  901. szStr, CharSizeOf(szStr) );
  902. break;
  903. case PR_CAR_TELEPHONE_NUMBER:
  904. cCopied = LoadString( hinstMapiX, idsPhoneLabelCar,
  905. szStr, CharSizeOf(szStr) );
  906. break;
  907. case PR_OTHER_TELEPHONE_NUMBER:
  908. cCopied = LoadString( hinstMapiX, idsPhoneLabelOther,
  909. szStr, CharSizeOf(szStr) );
  910. break;
  911. case PR_PAGER_TELEPHONE_NUMBER:
  912. cCopied = LoadString( hinstMapiX, idsPhoneLabelPager,
  913. szStr, CharSizeOf(szStr) );
  914. break;
  915. case PR_ASSISTANT_TELEPHONE_NUMBER:
  916. cCopied = LoadString( hinstMapiX, idsPhoneLabelAst,
  917. szStr, CharSizeOf(szStr) );
  918. break;
  919. case PR_HOME2_TELEPHONE_NUMBER:
  920. cCopied = LoadString( hinstMapiX, idsPhoneLabelHome2,
  921. szStr, CharSizeOf(szStr) );
  922. break;
  923. case PR_COMPANY_MAIN_PHONE_NUMBER:
  924. cCopied = LoadString( hinstMapiX, idsPhoneLabelCompMain,
  925. szStr, CharSizeOf(szStr) );
  926. break;
  927. case PR_BUSINESS_FAX_NUMBER:
  928. cCopied = LoadString( hinstMapiX, idsPhoneLabelFaxBus,
  929. szStr, CharSizeOf(szStr) );
  930. break;
  931. case PR_HOME_FAX_NUMBER:
  932. cCopied = LoadString( hinstMapiX, idsPhoneLabelFaxHome,
  933. szStr, CharSizeOf(szStr) );
  934. break;
  935. default:
  936. if(lpPropArray[i].ulPropTag == PR_WAB_IPPHONE)
  937. cCopied = LoadString( hinstMapiX, idsPhoneLabelIPPhone, szStr, CharSizeOf(szStr) );
  938. break;
  939. }
  940. if( cCopied > 0 )
  941. {
  942. LRESULT iItem;
  943. LPTSTR lpCompletePhNum = NULL;
  944. LPTSTR lpPhNum;
  945. int len = lstrlen( lpPropArray[i].Value.LPSZ ) + 1;
  946. lpPhNum = LocalAlloc(LMEM_ZEROINIT, sizeof( TCHAR ) * len );
  947. if( !lpPhNum )
  948. {
  949. DebugTrace(TEXT("cannot allocate memory for lpPhNum\n"));
  950. SendMessage(hWnd, IDCANCEL, (WPARAM)(0), (LPARAM)(0) );
  951. }
  952. lstrcpy(lpPhNum, lpPropArray[i].Value.LPSZ);
  953. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  954. szStr, 0, 0, (LPTSTR)&lpCompletePhNum, 0, (va_list *)&lpPropArray[i].Value.LPSZ);
  955. if( lpCompletePhNum )
  956. {
  957. iItem = SendDlgItemMessage( hWnd, IDC_NEWCALL_COMBO_PHNUM,
  958. CB_ADDSTRING, (WPARAM)(0), (LPARAM)(LPCTSTR)(lpCompletePhNum));
  959. }
  960. else
  961. iItem = CB_ERR;
  962. if( iItem == CB_ERR )
  963. {
  964. DebugTrace(TEXT("ERROR adding string %s"), lpCompletePhNum);
  965. }
  966. SendDlgItemMessage( hWnd, IDC_NEWCALL_COMBO_PHNUM,
  967. CB_SETITEMDATA, (WPARAM)(iItem), (LPARAM)(lpPhNum) );
  968. LocalFree(lpCompletePhNum);
  969. }
  970. }
  971. MAPIFreeBuffer(lpPropArray);
  972. }
  973. lpMailUser->lpVtbl->Release(lpMailUser);
  974. }
  975. }
  976. /**
  977. GetPhoneNumData: copies the data from the PHNUM combo to the szDestAddr buffer
  978. memory must have been allocated for szDestAddr
  979. [OUT] szDestAddr - buffer to be filled with the data from the comboBox
  980. returns the number of characters copied from combo_box to szDestAddr buffer
  981. */
  982. UINT GetPhoneNumData( HWND hDlg, LPTSTR szDestAddr)
  983. {
  984. LRESULT iIndex, iData;
  985. UINT cch = 0;
  986. TCHAR szBuff[MAX_PATH];
  987. // determine which index was selected
  988. iIndex = SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM,
  989. CB_GETCURSEL, (WPARAM)(0), (LPARAM)(0));
  990. // if nothing is selected then copy everything in the buffer
  991. // if( iIndex == CB_ERR)
  992. // {
  993. cch = (UINT) SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM, WM_GETTEXT,
  994. (WPARAM)(TAPIMAXDESTADDRESSSIZE), (LPARAM)(LPTSTR)(szDestAddr));
  995. /** }
  996. else
  997. {
  998. // otherwise obtain the data for the selected item
  999. iData = SendDlgItemMessage( hDlg, IDC_NEWCALL_COMBO_PHNUM,
  1000. CB_GETITEMDATA, (WPARAM)(iIndex), (LPARAM)(0) );
  1001. if( iData == CB_ERR )
  1002. {
  1003. cch = -1;
  1004. DebugTrace(TEXT("Unable to obtain data from ComboBox entry that should have data associated\n"));
  1005. }
  1006. else
  1007. {
  1008. // copy the item to a temp buffer
  1009. lstrcpy( szDestAddr, (LPCTSTR)iData);
  1010. DebugTrace(TEXT("String is %s\n"), szDestAddr );
  1011. DebugTrace(TEXT("Index was %d\n"), iIndex );
  1012. }
  1013. }
  1014. */
  1015. // a character count of 0 indicates there was no data for a particular item
  1016. return cch;
  1017. }
  1018. /**
  1019. HrSetComboText: a helper function that will set the text entry of the PHNUM combo
  1020. with just the telephone number (removing the description)
  1021. [IN] hCombo - the combo box to update, this must be the PHNUM combo.
  1022. */
  1023. HRESULT HrSetComboText(HWND hCombo)
  1024. {
  1025. LRESULT iIndex;
  1026. LPTSTR szData;
  1027. HRESULT hr = S_OK;
  1028. TCHAR szBuff[MAX_PATH], szDestAddr[TAPIMAXDESTADDRESSSIZE];
  1029. // determine which index was selected
  1030. iIndex = SendMessage( hCombo, CB_GETCURSEL, (WPARAM)(0), (LPARAM)(0));
  1031. if( iIndex != CB_ERR)
  1032. {
  1033. // obtain the data for the selected item
  1034. szData = (LPTSTR)SendMessage( hCombo, CB_GETITEMDATA, (WPARAM)(iIndex), (LPARAM)(0) );
  1035. if( (LRESULT)szData == CB_ERR )
  1036. {
  1037. DebugTrace(TEXT("Unable to obtain data from ComboBox entry that should have data associated\n"));
  1038. szData = szEmpty;
  1039. hr = E_FAIL;
  1040. }
  1041. else
  1042. {
  1043. LRESULT lr;
  1044. LPVOID lpData;
  1045. if( !szData )
  1046. szData = szEmpty;
  1047. // only copy the data after the offset stored for the item
  1048. lr = SendMessage( hCombo, CB_INSERTSTRING, (WPARAM)(iIndex), (LPARAM)(LPTSTR)(szData));
  1049. if( lr == CB_ERR || lr == CB_ERRSPACE)
  1050. {
  1051. DebugTrace(TEXT("unable to insert string = %s at index = %d \n"), szData, iIndex);
  1052. hr = E_FAIL;
  1053. }
  1054. lpData = (LPVOID)SendMessage( hCombo, CB_GETITEMDATA, (WPARAM)(iIndex+1), (LPARAM)(0) );
  1055. if( (LRESULT)lpData == CB_ERR )
  1056. {
  1057. DebugTrace(TEXT("unable to get data for %d"), iIndex+1);
  1058. hr = E_FAIL;
  1059. }
  1060. lr = SendMessage( hCombo, CB_SETITEMDATA, (WPARAM)(iIndex), (LPARAM)(lpData) );
  1061. if( lr == CB_ERR )
  1062. {
  1063. DebugTrace(TEXT("unable to set data at %d"), iIndex);
  1064. hr = E_FAIL;
  1065. }
  1066. lr = SendMessage( hCombo, CB_DELETESTRING, (WPARAM)(iIndex+1), (LPARAM)(0) );
  1067. if( lr == CB_ERR )
  1068. {
  1069. DebugTrace(TEXT("unable to delete string at %d"), iIndex+1);
  1070. hr = E_FAIL;
  1071. }
  1072. lr = SendMessage( hCombo, CB_SETCURSEL, (WPARAM)(iIndex), (LPARAM)(0) );
  1073. if( lr == CB_ERR )
  1074. {
  1075. DebugTrace(TEXT("unable to set selection at %d"), iIndex);
  1076. hr = E_FAIL;
  1077. }
  1078. }
  1079. }
  1080. else
  1081. hr = E_FAIL;
  1082. if( HR_FAILED(hr) )
  1083. DebugTrace(TEXT("settext failed\n"));
  1084. return hr;
  1085. }
  1086. /**
  1087. DisableCallBtnOnEmptyPhoneField: Will disable the call button if there is no text in
  1088. in the PHNUM combo box. Will enable the button if
  1089. text is present. Does not check to see if button is
  1090. already enabled/disabled, but enabling an enabled btn
  1091. should be fine.
  1092. */
  1093. void DisableCallBtnOnEmptyPhoneField(HWND hDlg)
  1094. {
  1095. HWND hComboItem = GetDlgItem( hDlg, IDC_NEWCALL_COMBO_PHNUM);
  1096. LRESULT iCurSel, iCurContSel;
  1097. iCurSel = SendMessage( hComboItem, CB_GETCURSEL, 0L, 0L );
  1098. iCurContSel = SendDlgItemMessage(hDlg, IDC_NEWCALL_COMBO_CONTACT, CB_GETCURSEL, (WPARAM)(0), (LPARAM)(0) );
  1099. if( iCurContSel < 0 || iCurContSel == CB_ERR)
  1100. SendMessage(hComboItem, CB_RESETCONTENT, 0L, 0L);
  1101. if( iCurSel < 0 || iCurSel == CB_ERR )
  1102. {
  1103. LRESULT cch;
  1104. TCHAR szBuf[MAX_PATH];
  1105. cch = SendMessage( hComboItem, WM_GETTEXT, (WPARAM)(CharSizeOf( szBuf) ),
  1106. (LPARAM)(szBuf) );
  1107. if( (INT)cch <= 0 || cch == CB_ERR)
  1108. {
  1109. // content will be empty at this point so can safely add
  1110. int cCopied;
  1111. LRESULT iIndex;
  1112. TCHAR szBuf[MAX_PATH];
  1113. cCopied = LoadString( hinstMapiX, idsNoPhoneNumAvailable,
  1114. szBuf, CharSizeOf(szBuf) );
  1115. iIndex = SendMessage(hComboItem, CB_ADDSTRING, (WPARAM)(0), (LPARAM)(szBuf));
  1116. SendMessage(hComboItem, CB_SETITEMDATA, (WPARAM)(0), (LPARAM)(0));
  1117. EnableWindow( GetDlgItem(hDlg, IDC_NEWCALL_BUTTON_CALL), FALSE);
  1118. return;
  1119. }
  1120. }
  1121. EnableWindow( GetDlgItem(hDlg, IDC_NEWCALL_BUTTON_CALL), TRUE);
  1122. }
  1123. VOID FAR PASCAL lineCallbackFunc( DWORD a, DWORD b, DWORD_PTR c, DWORD_PTR d, DWORD_PTR e, DWORD_PTR f)
  1124. {}
  1125. #ifdef _NT50_TAPI30
  1126. /**
  1127. HrLPSZCPToBSTR: (BSTR helper) helper to convert LPTSTR -> BST
  1128. */
  1129. HRESULT HrLPSZCPToBSTR(UINT cp, LPTSTR lpsz, BSTR *pbstr)
  1130. {
  1131. HRESULT hr = NOERROR;
  1132. BSTR bstr=0;
  1133. ULONG cch = 0, ccb,
  1134. cchRet;
  1135. if (!IsValidCodePage(cp))
  1136. cp = GetACP();
  1137. // get byte count
  1138. ccb = lstrlen(lpsz);
  1139. // get character count - DBCS string ccb may not equal to cch
  1140. cch=MultiByteToWideChar(cp, 0, lpsz, ccb, NULL, 0);
  1141. if(cch==0 && ccb!=0)
  1142. {
  1143. AssertSz(cch, TEXT("MultiByteToWideChar failed"));
  1144. hr=E_FAIL;
  1145. goto error;
  1146. }
  1147. // allocate a wide-string with enough character to hold string - use character count
  1148. bstr = (BSTR)LocalFree(LMEM_ZEROINIT, sizeof( BSTR ) * cch + 1);
  1149. if(!bstr)
  1150. {
  1151. hr=E_OUTOFMEMORY;
  1152. goto error;
  1153. }
  1154. cchRet=MultiByteToWideChar(cp, 0, lpsz, ccb, (LPWSTR)bstr, cch);
  1155. if(cchRet==0 && ccb!=0)
  1156. {
  1157. hr=E_FAIL;
  1158. goto error;
  1159. }
  1160. *pbstr = bstr;
  1161. bstr=0; // freed by caller
  1162. error:
  1163. if(bstr)
  1164. LocalFree(bstr);
  1165. return hr;
  1166. }
  1167. /**
  1168. HrLPSZToBSTR: Converts a LPTSTR to a BSTR using a helper function
  1169. */
  1170. HRESULT HrLPSZToBSTR(LPTSTR lpsz, BSTR *pbstr)
  1171. {
  1172. // GetACP so that it works on non-US platform
  1173. return HrLPSZCPToBSTR(GetACP(), lpsz, pbstr);
  1174. }
  1175. #endif //#ifdef _NT50_TAPI30