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.

1161 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. tapiutil.c
  5. Abstract:
  6. Utility functions for working with TAPI
  7. Environment:
  8. Windows fax driver user interface
  9. Revision History:
  10. 09/18/96 -davidx-
  11. Created it.
  12. 22/07/99 -v-sashab-
  13. Replaced a direct access to TAPI by Server calls
  14. mm/dd/yy -author-
  15. description
  16. --*/
  17. #include "faxui.h"
  18. #include "tapiutil.h"
  19. #define STRSAFE_NO_DEPRECATE
  20. #include <strsafe.h>
  21. #define UNKNOWN_DIALING_LOCATION (0xffffffff)
  22. static HLINEAPP g_hLineApp = 0;
  23. static DWORD g_dwTapiVersion = 0x00020000;
  24. static DWORD g_dwDefaultDialingLocation = UNKNOWN_DIALING_LOCATION;
  25. BOOL
  26. CurrentLocationUsesCallingCard ();
  27. VOID CALLBACK
  28. TapiLineCallback(
  29. DWORD hDevice,
  30. DWORD dwMessage,
  31. ULONG_PTR dwInstance,
  32. ULONG_PTR dwParam1,
  33. ULONG_PTR dwParam2,
  34. ULONG_PTR dwParam3
  35. )
  36. /*++
  37. Routine Description:
  38. TAPI line callback function: Even though we don't actually have anything
  39. to do here, we must provide a callback function to keep TAPI happy.
  40. Arguments:
  41. hDevice - Line or call handle
  42. dwMessage - Reason for the callback
  43. dwInstance - LINE_INFO index
  44. dwParam1 - Callback parameter #1
  45. dwParam2 - Callback parameter #2
  46. dwParam3 - Callback parameter #3
  47. Return Value:
  48. NONE
  49. --*/
  50. {
  51. }
  52. BOOL
  53. InitTapi ()
  54. {
  55. //
  56. // TAPI does not work properly on Win95
  57. // and does not relevant for remote fax connection
  58. //
  59. #ifdef UNICODE
  60. DWORD nLineDevs;
  61. LONG status;
  62. LINEINITIALIZEEXPARAMS lineInitParams;
  63. Assert (!g_hLineApp);
  64. if (g_hLineApp)
  65. {
  66. return TRUE;
  67. }
  68. ZeroMemory(&lineInitParams, sizeof(lineInitParams));
  69. lineInitParams.dwTotalSize =
  70. lineInitParams.dwNeededSize =
  71. lineInitParams.dwUsedSize = sizeof(lineInitParams);
  72. status = lineInitializeEx (&g_hLineApp,
  73. g_hModule,
  74. TapiLineCallback,
  75. TEXT("Fax Send Wizard"),
  76. &nLineDevs,
  77. &g_dwTapiVersion,
  78. &lineInitParams);
  79. if (NO_ERROR != status)
  80. {
  81. Error(("lineInitializeEx failed: %x\n", status));
  82. g_hLineApp = 0;
  83. return FALSE;
  84. }
  85. #endif // UNICODE
  86. return TRUE;
  87. }
  88. void
  89. ShutdownTapi ()
  90. {
  91. if (!g_hLineApp)
  92. {
  93. return;
  94. }
  95. //
  96. // Restore the last dialing location the user selected
  97. //
  98. if (UNKNOWN_DIALING_LOCATION != g_dwDefaultDialingLocation)
  99. {
  100. SetCurrentLocation (g_dwDefaultDialingLocation);
  101. }
  102. lineShutdown (g_hLineApp);
  103. g_hLineApp = 0;
  104. } // ShutdownTapi
  105. DWORD
  106. GetDefaultCountryID(
  107. VOID
  108. )
  109. /*++
  110. Routine Description:
  111. Return the default country ID for the current location
  112. Arguments:
  113. NONE
  114. Return Value:
  115. The current ID for the current location
  116. --*/
  117. {
  118. //
  119. // We assume the correct information has already been saved to the
  120. // registry during the installation process.
  121. //
  122. return 0;
  123. }
  124. PFAX_TAPI_LINECOUNTRY_ENTRY
  125. FindCountry(
  126. PFAX_TAPI_LINECOUNTRY_LIST pCountryList,
  127. DWORD countryId
  128. )
  129. /*++
  130. Routine Description:
  131. Find the specified country from a list of all countries and
  132. return a pointer to the corresponding FAX_TAPI_LINECOUNTRY_ENTRY structure
  133. Arguments:
  134. pCountryList - pointer to the country list
  135. countryId - Specifies the country ID we're interested in
  136. Return Value:
  137. Pointer to a FAX_TAPI_LINECOUNTRY_ENTRY structure corresponding to the specified country ID
  138. NULL if there is an error
  139. --*/
  140. {
  141. DWORD dwIndex;
  142. if (pCountryList == NULL || countryId == 0)
  143. return NULL;
  144. //
  145. // Look at each FAX_TAPI_LINECOUNTRY_ENTRY structure and compare its country ID with
  146. // the specified country ID
  147. //
  148. for (dwIndex=0; dwIndex < pCountryList->dwNumCountries; dwIndex++) {
  149. if (pCountryList->LineCountryEntries[dwIndex].dwCountryID == countryId)
  150. return &pCountryList->LineCountryEntries[dwIndex];
  151. }
  152. return NULL;
  153. }
  154. DWORD
  155. GetCountryIdFromCountryCode(
  156. PFAX_TAPI_LINECOUNTRY_LIST pCountryList,
  157. DWORD dwCountryCode
  158. )
  159. /*++
  160. Routine Description:
  161. Arguments:
  162. pCountryList - pointer to the country list
  163. dwCountryCode - Specifies the country code we're interested in
  164. Return Value:
  165. Country ID
  166. --*/
  167. {
  168. DWORD dwIndex;
  169. if (pCountryList == NULL || dwCountryCode == 0)
  170. return 0;
  171. //
  172. // Look at each FAX_TAPI_LINECOUNTRY_ENTRY structure and compare its country ID with
  173. // the specified country ID
  174. //
  175. for (dwIndex=0; dwIndex < pCountryList->dwNumCountries; dwIndex++) {
  176. if (pCountryList->LineCountryEntries[dwIndex].dwCountryCode == dwCountryCode)
  177. return pCountryList->LineCountryEntries[dwIndex].dwCountryID;
  178. }
  179. return 0;
  180. }
  181. INT
  182. AreaCodeRules(
  183. PFAX_TAPI_LINECOUNTRY_ENTRY pEntry
  184. )
  185. /*++
  186. Routine Description:
  187. Given a FAX_TAPI_LINECOUNTRY_ENTRY structure, determine if area code is needed in that country
  188. Arguments:
  189. pEntry - Points to a FAX_TAPI_LINECOUNTRY_ENTRY structure
  190. Return Value:
  191. AREACODE_DONTNEED - Area code is not used in the specified country
  192. AREACODE_OPTIONAL - Area code is optional in the specified country
  193. AREACODE_REQUIRED - Area code is required in the specified country
  194. --*/
  195. {
  196. if ((pEntry != NULL) &&
  197. (pEntry->lpctstrLongDistanceRule != 0))
  198. {
  199. //
  200. // Area code is required in this country
  201. //
  202. if (_tcschr(pEntry->lpctstrLongDistanceRule, TEXT('F')) != NULL)
  203. return AREACODE_REQUIRED;
  204. //
  205. // Area code is not needed in this country
  206. //
  207. if (_tcschr(pEntry->lpctstrLongDistanceRule, TEXT('I')) == NULL)
  208. return AREACODE_DONTNEED;
  209. }
  210. //
  211. // Default case: area code is optional in this country
  212. //
  213. return AREACODE_OPTIONAL;
  214. }
  215. VOID
  216. AssemblePhoneNumber(
  217. OUT LPTSTR pAddress,
  218. IN UINT cchAddress,
  219. IN DWORD countryCode,
  220. IN LPTSTR pAreaCode,
  221. IN LPTSTR pPhoneNumber
  222. )
  223. /*++
  224. Routine Description:
  225. Assemble a canonical phone number given the following:
  226. country code, area code, and phone number
  227. Arguments:
  228. pAddress - Specifies a buffer to hold the resulting fax address
  229. cchAddress - The size of the pAddress OUT buffer in TCHARs
  230. countryCode - Specifies the country code
  231. pAreaCode - Specifies the area code string
  232. pPhoneNumber - Specifies the phone number string
  233. Return Value:
  234. NONE
  235. --*/
  236. {
  237. //
  238. // Country code if neccessary
  239. //
  240. HRESULT hRc;
  241. if (countryCode != 0) {
  242. hRc = StringCchPrintf(pAddress,
  243. cchAddress,
  244. TEXT("+%d "),
  245. countryCode);
  246. if(FAILED(hRc))
  247. {
  248. Assert(0);
  249. return;
  250. }
  251. }
  252. //
  253. // Area code if necessary
  254. //
  255. if (pAreaCode && !IsEmptyString(pAreaCode)) {
  256. if (countryCode != 0)
  257. {
  258. hRc = StringCchCat(pAddress, cchAddress, TEXT("(") );
  259. if(FAILED(hRc))
  260. {
  261. Assert(0);
  262. return;
  263. }
  264. }
  265. hRc = StringCchCat(pAddress, cchAddress, pAreaCode);
  266. if(FAILED(hRc))
  267. {
  268. Assert(0);
  269. return;
  270. }
  271. if (countryCode != 0)
  272. {
  273. hRc = StringCchCat(pAddress, cchAddress, TEXT(")"));
  274. if(FAILED(hRc))
  275. {
  276. Assert(0);
  277. return;
  278. }
  279. }
  280. hRc = StringCchCat(pAddress, cchAddress, TEXT(" "));
  281. if(FAILED(hRc))
  282. {
  283. Assert(0);
  284. return;
  285. }
  286. }
  287. //
  288. // Phone number at last
  289. //
  290. Assert(pPhoneNumber != NULL);
  291. hRc = StringCchCat(pAddress, cchAddress, pPhoneNumber);
  292. if(FAILED(hRc))
  293. {
  294. Assert(0);
  295. }
  296. }
  297. VOID
  298. UpdateAreaCodeField(
  299. HWND hwndAreaCode,
  300. PFAX_TAPI_LINECOUNTRY_LIST pCountryList,
  301. DWORD countryId
  302. )
  303. /*++
  304. Routine Description:
  305. Update any area code text field associated with a country list box
  306. Arguments:
  307. hwndAreaCode - Specifies the text field associated with the country list box
  308. pCountryList - pointer to the country list
  309. countryId - Currently selected country ID
  310. Return Value:
  311. NONE
  312. --*/
  313. {
  314. if (hwndAreaCode == NULL)
  315. return;
  316. if (AreaCodeRules(FindCountry(pCountryList,countryId)) == AREACODE_DONTNEED) {
  317. SendMessage(hwndAreaCode, WM_SETTEXT, 0, (LPARAM) TEXT(""));
  318. EnableWindow(hwndAreaCode, FALSE);
  319. } else
  320. EnableWindow(hwndAreaCode, TRUE);
  321. }
  322. DWORD
  323. GetLocalCountryCode()
  324. /*++
  325. Routine Description:
  326. Retrieve local country code
  327. Arguments:
  328. None
  329. Return Value:
  330. Local country code if success
  331. NULL if failed
  332. --*/
  333. {
  334. HMODULE hTapi = NULL;
  335. TCHAR tszLocalCountryCode[16] = {0};
  336. TCHAR tszLocalCityCode[16] = {0};
  337. DWORD dwCountryCode = 0;
  338. typedef LONG (WINAPI *TAPI_GET_LOCATION_INFO)(LPTSTR, LPTSTR);
  339. TAPI_GET_LOCATION_INFO pfnTapiGetLocationInfo;
  340. hTapi = LoadLibrary(TEXT("tapi32.dll"));
  341. if(!hTapi)
  342. {
  343. Error(("LoadLibrary(tapi32.dll) failed. ec = 0x%X\n",GetLastError()));
  344. return dwCountryCode;
  345. }
  346. #ifdef UNICODE
  347. pfnTapiGetLocationInfo = (TAPI_GET_LOCATION_INFO)GetProcAddress(hTapi, "tapiGetLocationInfoW");
  348. #else
  349. pfnTapiGetLocationInfo = (TAPI_GET_LOCATION_INFO)GetProcAddress(hTapi, "tapiGetLocationInfoA");
  350. if(!pfnTapiGetLocationInfo)
  351. {
  352. pfnTapiGetLocationInfo = (TAPI_GET_LOCATION_INFO)GetProcAddress(hTapi, "tapiGetLocationInfo");
  353. }
  354. #endif
  355. if(pfnTapiGetLocationInfo)
  356. {
  357. if(0 == pfnTapiGetLocationInfo(tszLocalCountryCode, tszLocalCityCode))
  358. {
  359. if (1 != _stscanf(tszLocalCountryCode, TEXT("%u"), &dwCountryCode))
  360. {
  361. Error(("_stscanf failed."));
  362. dwCountryCode = 0;
  363. }
  364. }
  365. }
  366. else
  367. {
  368. Error(("tapiGetLocationInfo failed. ec = 0x%X\n",GetLastError()));
  369. }
  370. FreeLibrary(hTapi);
  371. return dwCountryCode;
  372. } // GetLocalCountryCode
  373. VOID
  374. InitCountryListBox(
  375. PFAX_TAPI_LINECOUNTRY_LIST pCountryList,
  376. HWND hwndList,
  377. HWND hwndAreaCode,
  378. LPTSTR lptstrCountry,
  379. DWORD countryId,
  380. BOOL bAddCountryCode
  381. )
  382. /*++
  383. Routine Description:
  384. Initialize the country list box
  385. Arguments:
  386. pCountryList - pointer to the country list
  387. hwndList - Handle to the country list box window
  388. hwndAreaCode - Handle to an associated area code text field
  389. lptstrCountry - Country that should be selected or NULL
  390. countryId - Initially selected country ID
  391. bAddCountryCode - if TRUE add a country code to a country name
  392. Return Value:
  393. NONE
  394. --*/
  395. #define MAX_COUNTRY_NAME 256
  396. {
  397. DWORD dwIndex;
  398. TCHAR buffer[MAX_COUNTRY_NAME]={0};
  399. if(0 == countryId)
  400. {
  401. //
  402. // if no country selected, select the local
  403. //
  404. countryId = GetLocalCountryCode();
  405. if(0 == countryId)
  406. {
  407. //
  408. // The default location is not configured.
  409. //
  410. DoTapiProps(hwndList);
  411. countryId = GetLocalCountryCode();
  412. }
  413. }
  414. //
  415. // Disable redraw on the list box and reset its content
  416. //
  417. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  418. SendMessage(hwndList, CB_RESETCONTENT, FALSE, 0);
  419. //
  420. // Loop through FAX_TAPI_LINECOUNTRY_ENTRY structures and add the available selections to
  421. // the country list box.
  422. //
  423. if (pCountryList)
  424. {
  425. TCHAR szFormat[64] = { TEXT("%s (%d)") };
  426. #ifdef UNICODE
  427. if(pCountryList->dwNumCountries &&
  428. IsWindowRTL(hwndList) &&
  429. !StrHasRTLChar(LOCALE_SYSTEM_DEFAULT, pCountryList->LineCountryEntries[0].lpctstrCountryName))
  430. {
  431. //
  432. // The Combo Box has RTL layout
  433. // but the country name has not RTL characters.
  434. // So, we add LEFT-TO-RIGHT OVERRIDE UNICODE character.
  435. //
  436. _tcscpy(szFormat, TEXT("\x202D%s (%d)"));
  437. }
  438. #endif
  439. for (dwIndex=0; dwIndex < pCountryList->dwNumCountries; dwIndex++)
  440. {
  441. if (pCountryList->LineCountryEntries[dwIndex].lpctstrCountryName)
  442. {
  443. if(bAddCountryCode)
  444. {
  445. _sntprintf(buffer,
  446. sizeof(buffer)/sizeof(buffer[0]) - 1,
  447. szFormat,
  448. pCountryList->LineCountryEntries[dwIndex].lpctstrCountryName,
  449. pCountryList->LineCountryEntries[dwIndex].dwCountryCode);
  450. }
  451. else
  452. {
  453. _tcsncpy(buffer,
  454. pCountryList->LineCountryEntries[dwIndex].lpctstrCountryName,
  455. sizeof(buffer)/sizeof(buffer[0]) - 1);
  456. }
  457. if (lptstrCountry && _tcsstr(buffer,lptstrCountry) && !countryId)
  458. {
  459. // search for a first occurence of lptstrCountry
  460. countryId = pCountryList->LineCountryEntries[dwIndex].dwCountryID;
  461. }
  462. SendMessage(hwndList,
  463. CB_SETITEMDATA,
  464. SendMessage(hwndList, CB_ADDSTRING, 0, (LPARAM) buffer),
  465. pCountryList->LineCountryEntries[dwIndex].dwCountryID);
  466. }
  467. }
  468. }
  469. //
  470. // Figure out which item in the list should be selected
  471. //
  472. if (pCountryList != NULL)
  473. {
  474. for (dwIndex=0; dwIndex <= pCountryList->dwNumCountries; dwIndex++)
  475. {
  476. if ((DWORD) SendMessage(hwndList, CB_GETITEMDATA, dwIndex, 0) == countryId)
  477. break;
  478. }
  479. if (dwIndex > pCountryList->dwNumCountries)
  480. {
  481. dwIndex = countryId = 0;
  482. }
  483. }
  484. else
  485. {
  486. dwIndex = countryId = 0;
  487. }
  488. SendMessage(hwndList, CB_SETCURSEL, dwIndex, 0);
  489. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  490. //
  491. // Update the associated area code text field
  492. //
  493. UpdateAreaCodeField(hwndAreaCode, pCountryList, countryId);
  494. }
  495. VOID
  496. SelChangeCountryListBox(
  497. HWND hwndList,
  498. HWND hwndAreaCode,
  499. PFAX_TAPI_LINECOUNTRY_LIST pCountryList
  500. )
  501. /*++
  502. Routine Description:
  503. Handle dialog selection changes in the country list box
  504. Arguments:
  505. hwndList - Handle to the country list box window
  506. hwndAreaCode - Handle to an associated area code text field
  507. pCountryList - pointer to the country list
  508. Return Value:
  509. NONE
  510. --*/
  511. {
  512. UpdateAreaCodeField(hwndAreaCode, pCountryList, GetCountryListBoxSel(hwndList));
  513. }
  514. DWORD
  515. GetCountryListBoxSel(
  516. HWND hwndList
  517. )
  518. /*++
  519. Routine Description:
  520. Return the current selection of country list box
  521. Arguments:
  522. hwndList - Handle to the country list box window
  523. Return Value:
  524. Currently selected country ID
  525. --*/
  526. {
  527. INT msgResult;
  528. if ((msgResult = (INT)SendMessage(hwndList, CB_GETCURSEL, 0, 0)) == CB_ERR ||
  529. (msgResult = (INT)SendMessage(hwndList, CB_GETITEMDATA, msgResult, 0)) == CB_ERR)
  530. {
  531. return 0;
  532. }
  533. return msgResult;
  534. }
  535. BOOL
  536. DoTapiProps(
  537. HWND hDlg
  538. )
  539. {
  540. DWORD dwRes;
  541. dwRes = lineTranslateDialog(g_hLineApp,
  542. 0, // Device ID
  543. g_dwTapiVersion,
  544. hDlg,
  545. NULL); // Address
  546. if(0 != dwRes)
  547. {
  548. Error(("lineTranslateDialog failed. ec = 0x%X\n", dwRes));
  549. return FALSE;
  550. }
  551. return TRUE;
  552. } // DoTapiProps
  553. LPLINETRANSLATECAPS
  554. GetTapiLocationInfo(
  555. HWND hWnd
  556. )
  557. /*++
  558. Routine Description:
  559. Get a list of locations from TAPI
  560. Arguments:
  561. NONE
  562. Return Value:
  563. Pointer to a LINETRANSLATECAPS structure,
  564. NULL if there is an error
  565. --*/
  566. #define INITIAL_LINETRANSLATECAPS_SIZE 5000
  567. {
  568. LPLINETRANSLATECAPS pTranslateCaps = NULL;
  569. //
  570. // TAPI does not work properly on Win95
  571. // and does not relevant for remote fax connection
  572. //
  573. #ifdef UNICODE
  574. DWORD cbNeeded = INITIAL_LINETRANSLATECAPS_SIZE;
  575. LONG status;
  576. INT i;
  577. if (!g_hLineApp)
  578. {
  579. return NULL;
  580. }
  581. for (i = 0; i < 2; i++)
  582. {
  583. //
  584. // Free any existing buffer and allocate a new one with larger size
  585. //
  586. MemFree(pTranslateCaps);
  587. if (! (pTranslateCaps = MemAlloc(cbNeeded)))
  588. {
  589. Error(("Memory allocation failed\n"));
  590. return NULL;
  591. }
  592. //
  593. // Get the LINETRANSLATECAPS structure from TAPI
  594. //
  595. pTranslateCaps->dwTotalSize = cbNeeded;
  596. status = lineGetTranslateCaps(g_hLineApp, g_dwTapiVersion, pTranslateCaps);
  597. //
  598. // Try to bring up UI if there are no locations.
  599. //
  600. if (LINEERR_INIFILECORRUPT == status)
  601. {
  602. if (lineTranslateDialog( g_hLineApp, 0, g_dwTapiVersion, hWnd, NULL ))
  603. {
  604. MemFree(pTranslateCaps);
  605. return NULL;
  606. }
  607. continue;
  608. }
  609. if ((pTranslateCaps->dwNeededSize > pTranslateCaps->dwTotalSize) ||
  610. (LINEERR_STRUCTURETOOSMALL == status) ||
  611. (LINEERR_NOMEM == status))
  612. {
  613. //
  614. // Retry since our initial estimated buffer size was too small
  615. //
  616. if (cbNeeded >= pTranslateCaps->dwNeededSize)
  617. {
  618. cbNeeded = cbNeeded * 5;
  619. }
  620. else
  621. {
  622. cbNeeded = pTranslateCaps->dwNeededSize;
  623. }
  624. Warning(("LINETRANSLATECAPS resized to: %d\n", cbNeeded));
  625. }
  626. else
  627. {
  628. //
  629. // Either success of real error - break now and let the code after the loop handle it.
  630. //
  631. break;
  632. }
  633. }
  634. if (NO_ERROR != status)
  635. {
  636. Error(("lineGetTranslateCaps failed: %x\n", status));
  637. MemFree(pTranslateCaps);
  638. SetLastError (status);
  639. pTranslateCaps = NULL;
  640. }
  641. if (pTranslateCaps)
  642. {
  643. //
  644. // Update the current default dialing location.
  645. // We save it here and restore it when the wizard exists in ShutdownTapi().
  646. //
  647. g_dwDefaultDialingLocation = pTranslateCaps->dwCurrentLocationID;
  648. }
  649. #endif // UNICODE
  650. return pTranslateCaps;
  651. } // GetTapiLocationInfo
  652. BOOL
  653. SetCurrentLocation(
  654. DWORD locationID
  655. )
  656. /*++
  657. Routine Description:
  658. Change the default TAPI location
  659. Arguments:
  660. locationID - The permanant ID for the new default TAPI location
  661. Return Value:
  662. TRUE if successful, FALSE if there is an error
  663. --*/
  664. {
  665. LONG lResult;
  666. Assert (g_hLineApp);
  667. if (!g_hLineApp)
  668. {
  669. SetLastError (ERROR_GEN_FAILURE);
  670. return FALSE;
  671. }
  672. lResult = lineSetCurrentLocation(g_hLineApp, locationID);
  673. if (NO_ERROR == lResult)
  674. {
  675. Verbose(("Current location changed: ID = %d\n", locationID));
  676. return TRUE;
  677. }
  678. else
  679. {
  680. Error(("Couldn't change current TAPI location\n"));
  681. SetLastError (lResult);
  682. return FALSE;
  683. }
  684. } // SetCurrentLocation
  685. BOOL
  686. TranslateAddress (
  687. LPCTSTR lpctstrCanonicalAddress,
  688. DWORD dwLocationId,
  689. LPTSTR *lpptstrDialableAndDisplayableAddress
  690. )
  691. /*++
  692. Routine name : TranslateAddress
  693. Routine description:
  694. Translates a canonical address
  695. Author:
  696. Eran Yariv (EranY), Feb, 2001
  697. Arguments:
  698. lpctstrCanonicalAddress [in] - Canonical address string
  699. dwLocationId [in] - Location id to use
  700. lpptstrDialableAndDisplayableAddress [out] - Allocated string holding a combination of translated
  701. dialable and displayable addresses
  702. Return Value:
  703. TRUE if successful, FALSE otherwise (sets last error0.
  704. --*/
  705. {
  706. //
  707. // TAPI does not work properly on Win95
  708. // and does not relevant for remote fax connection
  709. //
  710. #ifdef UNICODE
  711. DWORD dwLineTransOutSize = sizeof(LINETRANSLATEOUTPUT) + 4096;
  712. LPLINETRANSLATEOUTPUT lpTranslateOutput = NULL;
  713. LONG lRslt = ERROR_SUCCESS;
  714. DWORD dwRes;
  715. LPTSTR lptstrTranslatedDialableString;
  716. LPTSTR lptstrTranslatedDisplayableString;
  717. DWORD dwTranslatedStringsSize;
  718. BOOL bCanonicCheck;
  719. dwRes = IsCanonicalAddress(lpctstrCanonicalAddress, &bCanonicCheck, NULL, NULL, NULL);
  720. if (ERROR_SUCCESS != dwRes)
  721. {
  722. SetLastError (dwRes);
  723. return FALSE;
  724. }
  725. Assert (bCanonicCheck);
  726. if (!bCanonicCheck)
  727. {
  728. SetLastError (ERROR_GEN_FAILURE);
  729. return FALSE;
  730. }
  731. Assert (g_hLineApp);
  732. if (!g_hLineApp)
  733. {
  734. SetLastError (ERROR_GEN_FAILURE);
  735. return FALSE;
  736. }
  737. if (!SetCurrentLocation(dwLocationId))
  738. {
  739. return FALSE;
  740. }
  741. lpTranslateOutput = MemAlloc (dwLineTransOutSize);
  742. if (!lpTranslateOutput)
  743. {
  744. Error(("Couldn't allocate translation results buffer\n"));
  745. return FALSE;
  746. }
  747. lpTranslateOutput->dwTotalSize = dwLineTransOutSize;
  748. lRslt = lineTranslateAddress(
  749. g_hLineApp,
  750. 0,
  751. g_dwTapiVersion,
  752. lpctstrCanonicalAddress,
  753. 0,
  754. LINETRANSLATEOPTION_CANCELCALLWAITING,
  755. lpTranslateOutput
  756. );
  757. if ((lpTranslateOutput->dwNeededSize > lpTranslateOutput->dwTotalSize) ||
  758. (LINEERR_STRUCTURETOOSMALL == lRslt) ||
  759. (LINEERR_NOMEM == lRslt))
  760. {
  761. //
  762. // Retry since our initial estimated buffer size was too small
  763. //
  764. if (dwLineTransOutSize >= lpTranslateOutput->dwNeededSize)
  765. {
  766. dwLineTransOutSize = dwLineTransOutSize * 5;
  767. }
  768. else
  769. {
  770. dwLineTransOutSize = lpTranslateOutput->dwNeededSize;
  771. }
  772. //
  773. // Re-allocate the LineTransCaps structure
  774. //
  775. dwLineTransOutSize = lpTranslateOutput->dwNeededSize;
  776. MemFree(lpTranslateOutput);
  777. lpTranslateOutput = (LPLINETRANSLATEOUTPUT) MemAlloc(dwLineTransOutSize);
  778. if (!dwLineTransOutSize)
  779. {
  780. Error(("Couldn't allocate translation results buffer\n"));
  781. return FALSE;
  782. }
  783. lpTranslateOutput->dwTotalSize = dwLineTransOutSize;
  784. lRslt = lineTranslateAddress(
  785. g_hLineApp,
  786. 0,
  787. g_dwTapiVersion,
  788. lpctstrCanonicalAddress,
  789. 0,
  790. LINETRANSLATEOPTION_CANCELCALLWAITING,
  791. lpTranslateOutput
  792. );
  793. }
  794. if (ERROR_SUCCESS != lRslt)
  795. {
  796. //
  797. // Other error
  798. //
  799. Error(("lineGetTranslateAddress() failed, ec=0x%08x\n", lRslt));
  800. MemFree (lpTranslateOutput);
  801. SetLastError (lRslt);
  802. return FALSE;
  803. }
  804. //
  805. // We now hold the valid translated address in lpTranslateOutput
  806. //
  807. //
  808. // Calc required buffer size to hold combined strings.
  809. //
  810. if (CurrentLocationUsesCallingCard ())
  811. {
  812. //
  813. // Calling card is used.
  814. // TAPI returns credit card numbers in the displayable string.
  815. // return the input canonical number as the displayable string.
  816. //
  817. lptstrTranslatedDisplayableString = (LPTSTR)lpctstrCanonicalAddress;
  818. }
  819. else
  820. {
  821. //
  822. // Calling card isn't used - use displayable string as is.
  823. //
  824. Assert (lpTranslateOutput->dwDisplayableStringSize > 0);
  825. lptstrTranslatedDisplayableString = (LPTSTR)((LPBYTE)lpTranslateOutput + lpTranslateOutput->dwDisplayableStringOffset);
  826. }
  827. dwTranslatedStringsSize = _tcslen (lptstrTranslatedDisplayableString);
  828. Assert (lpTranslateOutput->dwDialableStringSize > 0);
  829. lptstrTranslatedDialableString = (LPTSTR)((LPBYTE)lpTranslateOutput + lpTranslateOutput->dwDialableStringOffset);
  830. dwTranslatedStringsSize += _tcslen (lptstrTranslatedDialableString);
  831. //
  832. // Add NULL + Formatting extra length
  833. //
  834. dwTranslatedStringsSize += COMBINED_TRANSLATED_STRING_EXTRA_LEN + 1;
  835. //
  836. // Allocate return buffer
  837. //
  838. *lpptstrDialableAndDisplayableAddress = (LPTSTR)MemAlloc (dwTranslatedStringsSize * sizeof (TCHAR));
  839. if (!*lpptstrDialableAndDisplayableAddress)
  840. {
  841. MemFree (lpTranslateOutput);
  842. Error(("Couldn't allocate translation results buffer\n"));
  843. return FALSE;
  844. }
  845. _stprintf (*lpptstrDialableAndDisplayableAddress,
  846. COMBINED_TRANSLATED_STRING_FORMAT,
  847. lptstrTranslatedDialableString,
  848. lptstrTranslatedDisplayableString);
  849. MemFree (lpTranslateOutput);
  850. return TRUE;
  851. #endif // UNICODE
  852. return FALSE;
  853. } // TranslateAddress
  854. BOOL
  855. CurrentLocationUsesCallingCard ()
  856. {
  857. LPLINETRANSLATECAPS pTranslateCaps = GetTapiLocationInfo (NULL);
  858. DWORD dwIndex;
  859. BOOL bRes = TRUE;
  860. LPLINELOCATIONENTRY pLocationEntry = NULL;
  861. if (!pTranslateCaps)
  862. {
  863. return TRUE;
  864. }
  865. //
  866. // Find current location
  867. //
  868. pLocationEntry = (LPLINELOCATIONENTRY)
  869. ((PBYTE) pTranslateCaps + pTranslateCaps->dwLocationListOffset);
  870. for (dwIndex = 0; dwIndex < pTranslateCaps->dwNumLocations; dwIndex++)
  871. {
  872. if (pLocationEntry->dwPermanentLocationID == pTranslateCaps->dwCurrentLocationID)
  873. {
  874. //
  875. // We found the current calling location
  876. // Let's see if it uses calling cards.
  877. //
  878. if (pLocationEntry->dwPreferredCardID)
  879. {
  880. bRes = TRUE;
  881. goto exit;
  882. }
  883. else
  884. {
  885. //
  886. // Not using calling card
  887. //
  888. bRes = FALSE;
  889. goto exit;
  890. }
  891. }
  892. pLocationEntry++;
  893. }
  894. exit:
  895. MemFree (pTranslateCaps);
  896. return bRes;
  897. } // CurrentLocationUsesCallingCard