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

990 lines
32 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: tapi.cpp
  4. //
  5. // Module: CMDIAL32.DLL
  6. //
  7. // Synopsis: The module contains the code related to TAPI.
  8. //
  9. // Copyright (c) 1996-1999 Microsoft Corporation
  10. //
  11. // Author: byao created 04/29/97
  12. // quintinb created Header 08/16/99
  13. //
  14. //+----------------------------------------------------------------------------
  15. #include "cmmaster.h"
  16. #include "unimodem.h"
  17. //
  18. // Local prototype
  19. //
  20. DWORD GetModemSpeakerMode(TapiLinkageStruct *ptlsTapiLink);
  21. //+----------------------------------------------------------------------------
  22. //
  23. // Function: TapiCallback
  24. //
  25. // Synopsis: NULL callback required param when intializing line
  26. //
  27. // Arguments: DWORD hDevice -
  28. // DWORD dwMsg -
  29. // DWORD dwCallbackInstance -
  30. // DWORD dwParam1 -
  31. // DWORD dwParam2 -
  32. // DWORD dwParam3 -
  33. //
  34. // Returns: Nothing
  35. //
  36. // History: nickball Created Header 7/7/99
  37. //
  38. //+----------------------------------------------------------------------------
  39. VOID FAR PASCAL TapiCallback(DWORD hDevice,
  40. DWORD dwMsg,
  41. DWORD dwCallbackInstance,
  42. DWORD dwParam1,
  43. DWORD dwParam2,
  44. DWORD dwParam3)
  45. {
  46. // nothing
  47. }
  48. //+----------------------------------------------------------------------------
  49. //
  50. // Function: OpenTapi
  51. //
  52. // Synopsis:
  53. //
  54. // Arguments: HINSTANCE hInst -
  55. // TapiLinkageStruct *ptlsTapiLink -
  56. //
  57. // Returns: BOOL -
  58. //
  59. // History: quintinb Created Header 5/1/99
  60. //
  61. //+----------------------------------------------------------------------------
  62. BOOL OpenTapi(HINSTANCE hInst, TapiLinkageStruct *ptlsTapiLink)
  63. {
  64. LONG lRes;
  65. if (ptlsTapiLink->bOpen)
  66. {
  67. return (TRUE);
  68. }
  69. if (!ptlsTapiLink->pfnlineInitialize || !ptlsTapiLink->pfnlineShutdown)
  70. {
  71. SetLastError(ERROR_PROC_NOT_FOUND);
  72. return (FALSE);
  73. }
  74. lRes = ptlsTapiLink->pfnlineInitialize(&ptlsTapiLink->hlaLine,
  75. hInst,
  76. TapiCallback,
  77. NULL,
  78. &ptlsTapiLink->dwDevCnt);
  79. CMTRACE3(TEXT("OpenTapi() lineInitialize() returns %u, hlaLine=0x%x, dwDevCnt=%u."),
  80. lRes, ptlsTapiLink->hlaLine, ptlsTapiLink->dwDevCnt);
  81. if (lRes != 0)
  82. {
  83. DWORD dwErr = ERROR_INVALID_PARAMETER;
  84. switch (lRes)
  85. {
  86. case LINEERR_REINIT:
  87. dwErr = ERROR_BUSY;
  88. break;
  89. case LINEERR_RESOURCEUNAVAIL:
  90. case LINEERR_NOMEM:
  91. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  92. break;
  93. }
  94. SetLastError(dwErr);
  95. return (FALSE);
  96. }
  97. ptlsTapiLink->bOpen = TRUE;
  98. ptlsTapiLink->bDevicePicked = FALSE;
  99. ptlsTapiLink->bModemSpeakerOff = FALSE;
  100. return (TRUE);
  101. }
  102. //+----------------------------------------------------------------------------
  103. //
  104. // Function: CloseTapi
  105. //
  106. // Synopsis: Helper function to clean up TAPI line.
  107. //
  108. // Arguments: TapiLinkageStruct *ptlsTapiLink - Our TAPI linkage struct
  109. //
  110. // Returns: Nothing
  111. //
  112. // History: nickball Created Header 7/7/99
  113. //
  114. //+----------------------------------------------------------------------------
  115. void CloseTapi(TapiLinkageStruct *ptlsTapiLink)
  116. {
  117. if (ptlsTapiLink->bOpen)
  118. {
  119. ptlsTapiLink->bOpen = FALSE;
  120. ptlsTapiLink->pfnlineShutdown(ptlsTapiLink->hlaLine);
  121. }
  122. }
  123. //+----------------------------------------------------------------------------
  124. //
  125. // Function: LinkToTapi
  126. //
  127. // Synopsis: Encapsulates the calling of LinkToDll with the correct table of
  128. // function names to be used therein with GetProcAddress
  129. //
  130. // Arguments: TapiLinkageStruct *ptlsTapiLink - The Tapi linkage struct to receive the function addresses
  131. // LPCTSTR pszTapi - The explicit name of the DLL
  132. //
  133. // Returns: BOOL - TRUE if fully linked
  134. //
  135. // History: nickball Created Header 12/31/97
  136. //
  137. //+----------------------------------------------------------------------------
  138. BOOL LinkToTapi(TapiLinkageStruct *ptlsTapiLink, LPCSTR pszTapi)
  139. {
  140. BOOL bRet = FALSE;
  141. if (OS_NT)
  142. {
  143. static LPCSTR apszTapi[] =
  144. {
  145. //
  146. // Several of the Tapi Functions don't have W versions. Use all the Unicode functions
  147. // that we can however.
  148. //
  149. "lineInitialize", // no W version
  150. "lineNegotiateAPIVersion", // no W version
  151. "lineGetDevCapsW",
  152. "lineGetDevConfig",
  153. "lineShutdown", // no W version
  154. "lineTranslateAddressW",
  155. "lineTranslateDialogW",
  156. "lineGetTranslateCaps",
  157. "lineSetCurrentLocation",
  158. NULL
  159. };
  160. MYDBGASSERT(sizeof(ptlsTapiLink->apvPfnTapi)/sizeof(ptlsTapiLink->apvPfnTapi[0])==sizeof(apszTapi)/sizeof(apszTapi[0]));
  161. bRet = LinkToDll(&ptlsTapiLink->hInstTapi,pszTapi,apszTapi,ptlsTapiLink->apvPfnTapi);
  162. }
  163. else
  164. {
  165. static LPCSTR apszTapi[] =
  166. {
  167. "lineInitialize",
  168. "lineNegotiateAPIVersion",
  169. "lineGetDevCaps",
  170. "lineGetDevConfig",
  171. "lineShutdown",
  172. "lineTranslateAddress",
  173. "lineTranslateDialog",
  174. "lineGetTranslateCaps",
  175. "lineSetCurrentLocation",
  176. NULL
  177. };
  178. MYDBGASSERT(sizeof(ptlsTapiLink->apvPfnTapi)/sizeof(ptlsTapiLink->apvPfnTapi[0])==sizeof(apszTapi)/sizeof(apszTapi[0]));
  179. bRet = LinkToDll(&ptlsTapiLink->hInstTapi,pszTapi,apszTapi,ptlsTapiLink->apvPfnTapi);
  180. }
  181. return bRet;
  182. }
  183. //+----------------------------------------------------------------------------
  184. //
  185. // Function: UnlinkFromTapi
  186. //
  187. // Synopsis: Helper function to release link to TAPI and clear linkage struct
  188. //
  189. // Arguments: TapiLinkageStruct *ptlsTapiLink - Ptr to our TAPI linkage struct
  190. //
  191. // Returns: Nothing
  192. //
  193. // History: nickball Created Header 7/7/99
  194. //
  195. // t-urama Modified 08/04/00 Access Points: Restore Tapi
  196. // location when CM was started
  197. //+----------------------------------------------------------------------------
  198. void UnlinkFromTapi(TapiLinkageStruct *ptlsTapiLink)
  199. {
  200. if (ptlsTapiLink->hInstTapi)
  201. {
  202. //
  203. // If we changed the original Tapi location, restore it
  204. //
  205. if (-1 != ptlsTapiLink->dwOldTapiLocation)
  206. {
  207. RestoreOldTapiLocation(ptlsTapiLink);
  208. }
  209. CloseTapi(ptlsTapiLink);
  210. FreeLibrary(ptlsTapiLink->hInstTapi);
  211. memset(ptlsTapiLink,0,sizeof(*ptlsTapiLink));
  212. }
  213. }
  214. LPTSTR GetModemFromLineDevCapsWithAlloc(LPLINEDEVCAPS pldcLineDevCaps)
  215. {
  216. LPTSTR pszTmp = NULL;
  217. if (OS_NT)
  218. {
  219. pszTmp = (LPTSTR) CmMalloc((pldcLineDevCaps->dwLineNameSize + 1)*sizeof(TCHAR));
  220. if (pszTmp)
  221. {
  222. LPTSTR pszPointerIntoTapiBuffer = LPTSTR((DWORD_PTR)pldcLineDevCaps + pldcLineDevCaps->dwLineNameOffset);
  223. lstrcpynU (pszTmp, pszPointerIntoTapiBuffer, pldcLineDevCaps->dwLineNameSize + 1);
  224. }
  225. }
  226. else
  227. {
  228. //
  229. // If this is Win9x, then we have an Ansi buffer that we need to convert to Unicode
  230. //
  231. LPSTR pszAnsiTmp = (LPSTR) CmMalloc((pldcLineDevCaps->dwLineNameSize + 1)*sizeof(CHAR));
  232. if (pszAnsiTmp)
  233. {
  234. LPSTR pszPointerIntoTapiBuffer = LPSTR((DWORD_PTR)pldcLineDevCaps + pldcLineDevCaps->dwLineNameOffset);
  235. lstrcpynA (pszAnsiTmp, pszPointerIntoTapiBuffer, pldcLineDevCaps->dwLineNameSize + 1);
  236. pszTmp = SzToWzWithAlloc(pszAnsiTmp);
  237. CmFree(pszAnsiTmp);
  238. }
  239. }
  240. return pszTmp;
  241. }
  242. BOOL SetTapiDevice(HINSTANCE hInst,
  243. TapiLinkageStruct *ptlsTapiLink,
  244. LPCTSTR pszModem)
  245. {
  246. BOOL bRet = TRUE;
  247. LONG lRes;
  248. DWORD dwTmp;
  249. LPLINEDEVCAPS pldcLineDevCaps;
  250. if (!OpenTapi(hInst,ptlsTapiLink))
  251. {
  252. return (FALSE);
  253. }
  254. if (ptlsTapiLink->bDevicePicked && (lstrcmpU(ptlsTapiLink->szDeviceName, pszModem) == 0))
  255. {
  256. return (TRUE);
  257. }
  258. CMTRACE1(TEXT("SetTapiDevice() looking for device name match with (%s)."), pszModem);
  259. ptlsTapiLink->bDevicePicked = FALSE;
  260. //
  261. // LineGetDevCaps has both an Ansi version (win9x) and a Unicode version. Thus we must use
  262. // the correct char size as needed.
  263. //
  264. dwTmp = sizeof(LINEDEVCAPS) + (2048 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR)));
  265. pldcLineDevCaps = (LPLINEDEVCAPS) CmMalloc(dwTmp);
  266. if (NULL == pldcLineDevCaps)
  267. {
  268. return FALSE;
  269. }
  270. pldcLineDevCaps->dwTotalSize = dwTmp;
  271. for (ptlsTapiLink->dwDeviceId=0; ptlsTapiLink->dwDeviceId < ptlsTapiLink->dwDevCnt; ptlsTapiLink->dwDeviceId++)
  272. {
  273. LINEEXTENSIONID leiLineExtensionId;
  274. lRes = ptlsTapiLink->pfnlineNegotiateAPIVersion(ptlsTapiLink->hlaLine,
  275. ptlsTapiLink->dwDeviceId,
  276. MIN_TAPI_VERSION,
  277. MAX_TAPI_VERSION,
  278. &ptlsTapiLink->dwApiVersion,
  279. &leiLineExtensionId);
  280. CMTRACE3(TEXT("******* SetTapiDevice() lineNegotiateAPIVersion(dwDeviceId=%u) returns %u, dwApiVersion=0x%x."),
  281. ptlsTapiLink->dwDeviceId, lRes, ptlsTapiLink->dwApiVersion);
  282. if (lRes == ERROR_SUCCESS)
  283. {
  284. lRes = ptlsTapiLink->pfnlineGetDevCaps(ptlsTapiLink->hlaLine,
  285. ptlsTapiLink->dwDeviceId,
  286. ptlsTapiLink->dwApiVersion,
  287. 0,
  288. pldcLineDevCaps);
  289. CMTRACE2(TEXT("SetTapiDevice() lineGetDevCaps(dwDeviceId=%u) returns %u."),
  290. ptlsTapiLink->dwDeviceId, lRes);
  291. if (lRes == ERROR_SUCCESS)
  292. {
  293. //
  294. // Copy out the device name according to reported offset and
  295. // length. Don't assume that its a NULL terminated string.
  296. //
  297. LPTSTR pszTmp = GetModemFromLineDevCapsWithAlloc(pldcLineDevCaps);
  298. if (pszTmp)
  299. {
  300. //
  301. // Okay, we have a device name from TAPI, first try to do a straight
  302. // comparision with the one we are looking for
  303. //
  304. CMTRACE1(TEXT("SetTapiDevice() - examining LineName of (%s)."), pszTmp);
  305. if (0 == lstrcmpU(pszModem, pszTmp))
  306. {
  307. ptlsTapiLink->bDevicePicked = TRUE;
  308. }
  309. else
  310. {
  311. //
  312. // We didn't find a straight match but that doesn't mean that
  313. // this isn't our device. On NT, RAS keeps its device names in ANSI
  314. // internally. Thus we can try roundtripping the string to MBCS and
  315. // back and see if they match now. Another possibility is that this
  316. // is an ISDN device, because on NT4 the RAS name and TAPI name are
  317. // different for ISDN devices. So, instead of checking the LineName
  318. // we should check the ProviderInfo (it is concatenation of two NULL terminated strings
  319. // and the second string is the used by RAS as device name)
  320. //
  321. if (OS_NT)
  322. {
  323. DWORD dwSize = WzToSz(pszTmp, NULL, 0); // cannot use WzToSzWithAlloc or we would get asserts
  324. // that the string didn't roundtrip on debug builds.
  325. // The point here is not to have it round trip so
  326. // that is what we want but we don't want to assert.
  327. if (0 != dwSize)
  328. {
  329. LPSTR pszAnsiTmp = (LPSTR)CmMalloc(dwSize*sizeof(CHAR));
  330. if (pszAnsiTmp)
  331. {
  332. if (WzToSz(pszTmp, pszAnsiTmp, dwSize))
  333. {
  334. LPWSTR pszRoundTripped = SzToWzWithAlloc(pszAnsiTmp);
  335. if (pszRoundTripped)
  336. {
  337. if (0 == lstrcmpU(pszModem, pszRoundTripped))
  338. {
  339. ptlsTapiLink->bDevicePicked = TRUE;
  340. }
  341. }
  342. CmFree(pszRoundTripped);
  343. }
  344. CmFree(pszAnsiTmp);
  345. }
  346. }
  347. //
  348. // Okay, check for an ISDN device name if it is one
  349. //
  350. if (!ptlsTapiLink->bDevicePicked)
  351. {
  352. //
  353. // Copy out the provider info according to reported offset
  354. // and length. Don't assume that its NULL terminated.
  355. //
  356. CmFree(pszTmp);
  357. pszTmp = (LPTSTR) CmMalloc((pldcLineDevCaps->dwProviderInfoSize + 1)*sizeof(TCHAR));
  358. if (pszTmp)
  359. {
  360. lstrcpynU(pszTmp, (LPTSTR)((LPBYTE)pldcLineDevCaps + pldcLineDevCaps->dwProviderInfoOffset), (pldcLineDevCaps->dwProviderInfoSize + 1));
  361. //
  362. // We should do this only if the device type is ISDN
  363. // The device type is the first string in the ProviderInfo
  364. //
  365. CMTRACE1(TEXT("SetTapiDevice() - examining ProviderInfo of (%s) for match with (RASDT_Isdn)."), pszTmp);
  366. if (0 == lstrcmpiU(pszTmp, RASDT_Isdn))
  367. {
  368. ptlsTapiLink->bDevicePicked = TRUE;
  369. }
  370. }
  371. }
  372. }
  373. }
  374. }
  375. //
  376. // If we found a device, then we need to copy the name over
  377. //
  378. if (ptlsTapiLink->bDevicePicked)
  379. {
  380. lstrcpynU(ptlsTapiLink->szDeviceName, pszModem, CELEMS(ptlsTapiLink->szDeviceName));
  381. if (OS_NT)
  382. {
  383. dwTmp = GetModemSpeakerMode(ptlsTapiLink);
  384. if (-1 != dwTmp && MDMSPKR_OFF == dwTmp)
  385. {
  386. ptlsTapiLink->bModemSpeakerOff = TRUE;
  387. }
  388. }
  389. //
  390. // We found a device, stop looking...
  391. //
  392. CmFree(pszTmp);
  393. break;
  394. }
  395. CmFree(pszTmp);
  396. }
  397. }
  398. }
  399. CmFree(pldcLineDevCaps);
  400. bRet = ptlsTapiLink->bDevicePicked;
  401. return bRet;
  402. }
  403. //+----------------------------------------------------------------------------
  404. //
  405. // Function: GetModemSpeakerMode
  406. //
  407. // Synopsis: Queries Modem settings for Speaker modeof a modem device.
  408. //
  409. // Arguments: TapiLinkageStruct *ptlsTapiLink - Ptr to TAPI linkage
  410. //
  411. // Returns: DWORD - The speaker mode for a valid modem device or 0xFFFFFFFF
  412. //
  413. // History: nickball Created 7/7/99
  414. //
  415. //+----------------------------------------------------------------------------
  416. DWORD GetModemSpeakerMode(TapiLinkageStruct *ptlsTapiLink)
  417. {
  418. DWORD dwRet = -1;
  419. LPVARSTRING lpVar = (LPVARSTRING) CmMalloc(sizeof(VARSTRING));
  420. //
  421. // Get the required buffer size by querying the config.
  422. //
  423. if (lpVar)
  424. {
  425. lpVar->dwTotalSize = sizeof(VARSTRING);
  426. lpVar->dwUsedSize = lpVar->dwTotalSize;
  427. DWORD dwRet = ptlsTapiLink->pfnlineGetDevConfig(ptlsTapiLink->dwDeviceId, lpVar, "comm/datamodem/dialout");
  428. if (LINEERR_STRUCTURETOOSMALL == dwRet || lpVar->dwNeededSize > lpVar->dwTotalSize)
  429. {
  430. //
  431. // We need a bigger buffer, re-allocate
  432. //
  433. DWORD dwTmp = lpVar->dwNeededSize;
  434. CmFree(lpVar);
  435. lpVar = (LPVARSTRING) CmMalloc(dwTmp);
  436. if (lpVar)
  437. {
  438. lpVar->dwTotalSize = dwTmp;
  439. lpVar->dwUsedSize = lpVar->dwTotalSize;
  440. //
  441. // Now get the actual config
  442. //
  443. dwRet = ptlsTapiLink->pfnlineGetDevConfig(ptlsTapiLink->dwDeviceId, lpVar, "comm/datamodem/dialout");
  444. if (ERROR_SUCCESS != dwRet)
  445. {
  446. CmFree(lpVar);
  447. lpVar = NULL;
  448. }
  449. }
  450. }
  451. }
  452. //
  453. // If we don't have a valid VARSTRING something failed, error out.
  454. //
  455. if (NULL == lpVar)
  456. {
  457. return -1;
  458. }
  459. //
  460. // We have a VARSTRING for the "dialout" config,
  461. // get the MODEMSETTINGS info. and see how the
  462. // modem speaker is configured.
  463. //
  464. PUMDEVCFG lpDevConfig = NULL;
  465. LPCOMMCONFIG lpCommConfig = NULL;
  466. LPMODEMSETTINGS lpModemSettings = NULL;
  467. if (lpVar->dwStringFormat == STRINGFORMAT_BINARY &&
  468. lpVar->dwStringSize >= sizeof(UMDEVCFG))
  469. {
  470. lpDevConfig = (PUMDEVCFG)
  471. ((LPBYTE) lpVar + lpVar->dwStringOffset);
  472. lpCommConfig = &lpDevConfig->commconfig;
  473. //
  474. // Check modems only
  475. //
  476. if (lpCommConfig->dwProviderSubType == PST_MODEM)
  477. {
  478. lpModemSettings = (LPMODEMSETTINGS)((LPBYTE) lpCommConfig +
  479. lpCommConfig->dwProviderOffset);
  480. dwRet = lpModemSettings->dwSpeakerMode;
  481. }
  482. }
  483. CmFree(lpVar);
  484. return dwRet;
  485. }
  486. //+----------------------------------------------------------------------------
  487. //
  488. // Func: MungePhone
  489. //
  490. // Desc: call TAPI to do phone dial info translation
  491. //
  492. // Args: [pszModem] - IN, modem string
  493. // [ppszPhone] - INOUT, phone number for display
  494. // [ptlsTapiLink] - IN, argument string for connect action
  495. // [hInst] - IN, instance handle (needed to call TAPI)
  496. // [fDialingRules] - are dialing rules enabled
  497. // [ppszDial] - OUT, dialable phone number
  498. // [fAccessPointsEnabled] - IN, are access points enabled
  499. // Return: LRESULT
  500. //
  501. // Notes:
  502. //
  503. // History: 01-Mar-2000 SumitC Added header block
  504. // 04-Mar-2000 SumitC fixed case for dialing rules not enabled
  505. // 04-Aug-2000 t-urama Added changing the TAPI location based on access point
  506. //
  507. //-----------------------------------------------------------------------------
  508. LRESULT MungePhone(LPCTSTR pszModem,
  509. LPTSTR *ppszPhone,
  510. TapiLinkageStruct *ptlsTapiLink,
  511. HINSTANCE hInst,
  512. BOOL fDialingRules,
  513. LPTSTR *ppszDial,
  514. BOOL fAccessPointsEnabled)
  515. {
  516. LPLINETRANSLATEOUTPUT pltoOutput = NULL;
  517. DWORD dwLen;
  518. LPWSTR pszDisplayable = NULL;
  519. LPWSTR pszDialable = NULL;
  520. LPSTR pszAnsiDisplayable = NULL;
  521. LPSTR pszAnsiDialable = NULL;
  522. LPTSTR pszOriginalPhoneNumber = NULL;
  523. LRESULT lRes = ERROR_INVALID_PARAMETER;
  524. //
  525. // Check the input params. Note that ppszDial could be NULL.
  526. //
  527. if ((NULL == pszModem) || (NULL == ppszPhone) || (NULL == *ppszPhone) || (NULL == ptlsTapiLink) || (NULL == hInst))
  528. {
  529. lRes = ERROR_INVALID_PARAMETER;
  530. CMASSERTMSG(FALSE, TEXT("MungePhone - invalid param."));
  531. goto done;
  532. }
  533. if (!SetTapiDevice(hInst, ptlsTapiLink, pszModem))
  534. {
  535. lRes = ERROR_NOT_FOUND;
  536. goto done;
  537. }
  538. if (FALSE == fDialingRules)
  539. {
  540. pszOriginalPhoneNumber = CmStrCpyAlloc(*ppszPhone);
  541. }
  542. if (TRUE == fDialingRules)
  543. {
  544. if (fAccessPointsEnabled)
  545. {
  546. //
  547. // Access Points are enabled. we now have to change the TAPI location
  548. // to that of the current access point. First get the current TAPI
  549. // location from TAPI
  550. //
  551. DWORD dwRet = GetCurrentTapiLocation(ptlsTapiLink);
  552. if (-1 == dwRet)
  553. {
  554. lRes = ERROR_NOT_FOUND;
  555. goto done;
  556. }
  557. if ((0 != ptlsTapiLink->dwTapiLocationForAccessPoint) && (dwRet != ptlsTapiLink->dwTapiLocationForAccessPoint))
  558. {
  559. //
  560. // The current TAPI location is different from the access point TAPI location
  561. // Change it. Note that if the current TAPI location is 0, this just means we haven't written
  562. // one for the favorite yet. Don't try to change it as SetCurrentTapiLocation will error out.
  563. //
  564. lRes = SetCurrentTapiLocation(ptlsTapiLink, ptlsTapiLink->dwTapiLocationForAccessPoint);
  565. if (lRes != ERROR_SUCCESS)
  566. {
  567. CMASSERTMSG(FALSE, TEXT("MungePhone -- unable to set the current TAPI location."));
  568. goto done;
  569. }
  570. CMTRACE1(TEXT("MungePhone() - Changed TAPI location to %u."), ptlsTapiLink->dwTapiLocationForAccessPoint);
  571. //
  572. // Save the TAPI location that was being used when CM started.
  573. // This will be restored when CM exits
  574. //
  575. if (-1 == ptlsTapiLink->dwOldTapiLocation)
  576. {
  577. ptlsTapiLink->dwOldTapiLocation = dwRet;
  578. CMTRACE1(TEXT("Saved TAPI location used when CM started, location is %d"), ptlsTapiLink->dwOldTapiLocation);
  579. }
  580. }
  581. }
  582. }
  583. //
  584. // Setup buffer for output, make sure to size the CHARs properly
  585. //
  586. dwLen = sizeof(*pltoOutput) + (1024 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR)));
  587. pltoOutput = (LPLINETRANSLATEOUTPUT) CmMalloc(dwLen);
  588. if (NULL == pltoOutput)
  589. {
  590. lRes = ERROR_NOT_ENOUGH_MEMORY;
  591. goto done;
  592. }
  593. pltoOutput->dwTotalSize = dwLen;
  594. //
  595. // Do the translation
  596. //
  597. if (OS_NT)
  598. {
  599. lRes = ptlsTapiLink->pfnlineTranslateAddress(ptlsTapiLink->hlaLine,
  600. ptlsTapiLink->dwDeviceId,
  601. ptlsTapiLink->dwApiVersion,
  602. *ppszPhone,
  603. 0,
  604. LINETRANSLATEOPTION_CANCELCALLWAITING,
  605. pltoOutput);
  606. }
  607. else
  608. {
  609. LPSTR pszAnsiPhone = WzToSzWithAlloc(*ppszPhone);
  610. if (pszAnsiPhone)
  611. {
  612. //
  613. // Note that the Cast on parameter 4 is to fake out the compiler,
  614. // rather than building a full set of "U" infrastructure for
  615. // the tapi linkage when only a couple of TAPI calls take strings.
  616. //
  617. lRes = ptlsTapiLink->pfnlineTranslateAddress(ptlsTapiLink->hlaLine,
  618. ptlsTapiLink->dwDeviceId,
  619. ptlsTapiLink->dwApiVersion,
  620. (LPWSTR)pszAnsiPhone,
  621. 0,
  622. LINETRANSLATEOPTION_CANCELCALLWAITING,
  623. pltoOutput);
  624. }
  625. CmFree(pszAnsiPhone);
  626. }
  627. CMTRACE3(TEXT("MungePhone(Modem=%s,Phone=%s) lineTranslateAddress(DeviceId=%u)"),
  628. MYDBGSTR(pszModem), MYDBGSTR(*ppszPhone), ptlsTapiLink->dwDeviceId);
  629. CMTRACE1(TEXT("\treturns %u."), lRes);
  630. if (lRes == ERROR_SUCCESS)
  631. {
  632. //
  633. // Get ptrs to displayable and dialable variations
  634. //
  635. LPBYTE pBase = (LPBYTE) pltoOutput;
  636. if (OS_NT)
  637. {
  638. pszDisplayable = (LPTSTR) (pBase + pltoOutput->dwDisplayableStringOffset);
  639. pszDialable = (LPTSTR) (pBase + pltoOutput->dwDialableStringOffset);
  640. }
  641. else
  642. {
  643. pszAnsiDisplayable = (LPSTR)(pBase + pltoOutput->dwDisplayableStringOffset);
  644. pszAnsiDialable = (LPSTR)(pBase + pltoOutput->dwDialableStringOffset);
  645. }
  646. }
  647. done:
  648. CmFree(*ppszPhone);
  649. *ppszPhone = NULL;
  650. if (ppszDial)
  651. {
  652. CmFree(*ppszDial);
  653. *ppszDial = NULL;
  654. }
  655. // Allocate buffers using the ptr ptrs specified by the caller
  656. // and fill them with the displayable and dialable versions
  657. if (ERROR_SUCCESS == lRes)
  658. {
  659. if (OS_NT)
  660. {
  661. if (fDialingRules)
  662. {
  663. *ppszPhone = CmStrCpyAlloc(pszDisplayable);
  664. }
  665. else
  666. {
  667. *ppszPhone = CmStrCpyAlloc(pszOriginalPhoneNumber);
  668. }
  669. }
  670. else
  671. {
  672. if (fDialingRules)
  673. {
  674. *ppszPhone = SzToWzWithAlloc(pszAnsiDisplayable);
  675. }
  676. else
  677. {
  678. *ppszPhone = CmStrCpyAlloc(pszOriginalPhoneNumber);
  679. }
  680. }
  681. MYDBGASSERT(*ppszPhone);
  682. if (*ppszPhone)
  683. {
  684. //
  685. // TAPI prepends a space, so trim the displayable number.
  686. //
  687. CmStrTrim(*ppszPhone);
  688. SingleSpace(*ppszPhone, (lstrlenU(*ppszPhone) + 1));
  689. }
  690. else
  691. {
  692. //
  693. // If we failed to alloc *ppszPhone, continue because we don't
  694. // depend on it below but we want the return code to be a failure.
  695. //
  696. lRes = ERROR_NOT_ENOUGH_MEMORY;
  697. }
  698. if (ppszDial)
  699. {
  700. if (OS_NT)
  701. {
  702. if (fDialingRules)
  703. {
  704. *ppszDial = CmStrCpyAlloc(pszDialable);
  705. }
  706. else
  707. {
  708. UINT uLen = 2 + lstrlenU(pszOriginalPhoneNumber);// 2 == one for NULL term and one for first char of pszDialable
  709. *ppszDial = (LPTSTR) CmMalloc(sizeof(TCHAR)*uLen);
  710. if (*ppszDial)
  711. {
  712. (*ppszDial)[0] = pszDialable[0];
  713. lstrcpynU((*ppszDial + 1), pszOriginalPhoneNumber, uLen - 1);
  714. }
  715. }
  716. }
  717. else
  718. {
  719. if (fDialingRules)
  720. {
  721. *ppszDial = SzToWzWithAlloc(pszAnsiDialable);
  722. }
  723. else
  724. {
  725. UINT uLen = 2 + lstrlenU(pszOriginalPhoneNumber);// 2 == one for NULL term and one for first char of pszDialable
  726. *ppszDial = (LPTSTR) CmMalloc(sizeof(TCHAR)*uLen);
  727. if (*ppszDial)
  728. {
  729. int lRet = MultiByteToWideChar(CP_ACP, 0, pszAnsiDialable, 1, *ppszDial, 1);
  730. lstrcpynU((*ppszDial + lRet), pszOriginalPhoneNumber, uLen - lRet);
  731. }
  732. }
  733. }
  734. }
  735. }
  736. if (FALSE == fDialingRules)
  737. {
  738. CmFree(pszOriginalPhoneNumber);
  739. }
  740. CmFree(pltoOutput);
  741. return (lRes);
  742. }
  743. //+----------------------------------------------------------------------------
  744. //
  745. // Func: GetCurrentTapiLocation
  746. //
  747. // Desc: get the current Tapi location
  748. //
  749. // Args: [ptlsTapiLink] - IN, Ptr to TAPI linkage
  750. //
  751. // Return: DWORD dwCurrentLoc - Current Tapi Location
  752. //
  753. // Notes:
  754. //
  755. // History: t-urama 07/21/2000 Created
  756. //-----------------------------------------------------------------------------
  757. DWORD GetCurrentTapiLocation(TapiLinkageStruct *ptlsTapiLink)
  758. {
  759. MYDBGASSERT(ptlsTapiLink->pfnlineGetTranslateCaps);
  760. if (!ptlsTapiLink->pfnlineGetTranslateCaps)
  761. {
  762. SetLastError(ERROR_PROC_NOT_FOUND);
  763. return (-1);
  764. }
  765. LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  766. DWORD dwLen;
  767. LRESULT lRes;
  768. DWORD dwRes = -1;
  769. dwLen = sizeof(*lpTranslateCaps) + (1024 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR)));
  770. do
  771. {
  772. CmFree(lpTranslateCaps);
  773. lpTranslateCaps = (LPLINETRANSLATECAPS) CmMalloc(dwLen);
  774. MYDBGASSERT(lpTranslateCaps);
  775. if (NULL == lpTranslateCaps)
  776. {
  777. lRes = ERROR_NOT_ENOUGH_MEMORY;
  778. break;
  779. }
  780. lpTranslateCaps->dwTotalSize = dwLen;
  781. lRes = ptlsTapiLink->pfnlineGetTranslateCaps(ptlsTapiLink->hlaLine,
  782. ptlsTapiLink->dwApiVersion,
  783. lpTranslateCaps);
  784. if (LINEERR_STRUCTURETOOSMALL == lRes)
  785. {
  786. dwLen = lpTranslateCaps->dwNeededSize;
  787. }
  788. } while(LINEERR_STRUCTURETOOSMALL == lRes);
  789. if (ERROR_SUCCESS != lRes)
  790. {
  791. CMTRACE1(TEXT("lineGetTranslateCaps returns error code %u."), lRes);
  792. }
  793. else
  794. {
  795. dwRes = lpTranslateCaps->dwCurrentLocationID;
  796. }
  797. CmFree(lpTranslateCaps);
  798. return dwRes;
  799. }
  800. //+----------------------------------------------------------------------------
  801. //
  802. // Func: SetCurrentTapiLocation
  803. //
  804. // Desc: Set the current Tapi location
  805. //
  806. // Args: TapiLinkageStruct *ptlsTapiLink - Ptr to TAPI linkage
  807. // DWORD dwLocation - New location
  808. //
  809. // Return: DWORD - Error code
  810. //
  811. // Notes:
  812. //
  813. // History: t-urama 07/21/2000 Created
  814. //-----------------------------------------------------------------------------
  815. DWORD SetCurrentTapiLocation(TapiLinkageStruct *ptlsTapiLink, DWORD dwLocation)
  816. {
  817. MYDBGASSERT(ptlsTapiLink->pfnlineSetCurrentLocation);
  818. if (!ptlsTapiLink->pfnlineSetCurrentLocation)
  819. {
  820. SetLastError(ERROR_PROC_NOT_FOUND);
  821. return (-1);
  822. }
  823. DWORD dwRes = 0;
  824. dwRes = ptlsTapiLink->pfnlineSetCurrentLocation(ptlsTapiLink->hlaLine, dwLocation);
  825. return dwRes;
  826. }
  827. //+----------------------------------------------------------------------------
  828. //
  829. // Func: RestoreOldTapiLocation
  830. //
  831. // Desc: Restore the Tapi location to the one when CM was started
  832. //
  833. // Args: TapiLinkageStruct *ptlsTapiLink - IN, Ptr to TAPI linkage
  834. //
  835. // Return: Nothing
  836. //
  837. // Notes:
  838. //
  839. // History: t-urama 07/21/2000 Created
  840. //-----------------------------------------------------------------------------
  841. void RestoreOldTapiLocation(TapiLinkageStruct *ptlsTapiLink)
  842. {
  843. if (ptlsTapiLink->dwOldTapiLocation != ptlsTapiLink->dwTapiLocationForAccessPoint)
  844. {
  845. SetCurrentTapiLocation(ptlsTapiLink, ptlsTapiLink->dwOldTapiLocation);
  846. }
  847. }