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.

1356 lines
40 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dial.c
  6. * Content: Wrappers for TAPI routines
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 6/10/96 kipo created it
  12. * 6/22/96 kipo close com port when disconnected; allow checking for
  13. * valid TAPI lines during NewComPort().
  14. * 7/08/96 kipo added support for new dialogs
  15. * 8/10/96 kipo added support for dialing location
  16. * 1/06/97 kipo updated for objects
  17. * 1/24/97 kipo bug #5400: Compaq Presario was overwriting the dev caps
  18. * buffer, causing a crash. Fixed to allocated a larger
  19. * buffer with some slop as a workaround.
  20. * 3/04/97 kipo close com port handle when deallocating call; use string
  21. * table for modem strings; updated debug output.
  22. * 3/24/97 kipo added support for specifying which modem to use
  23. * 4/08/97 kipo added support for separate modem and serial baud rates
  24. * 5/07/97 kipo added support for modem choice list
  25. * 5/23/97 kipo added support return status codes
  26. * 4/21/98 a-peterz #22920 Handle LINE_CLOSE message
  27. * 5/07/98 a-peterz #15251 Track call errors in DPDIAL
  28. * 10/13/99 johnkan #413516 - Mismatch between modem dialog selection and TAPI device ID
  29. *@@END_MSINTERNAL
  30. ***************************************************************************/
  31. #include <windows.h>
  32. #include <windowsx.h>
  33. #include "dputils.h"
  34. #include "macros.h"
  35. #include "dial.h"
  36. void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
  37. DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3);
  38. void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  39. void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  40. void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  41. void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege);
  42. void ProcessReplyMessage(LPDPDIAL globals, DWORD asyncID, LINERESULT lResult);
  43. LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet);
  44. LINERESULT dialGetCommHandle(LPDPDIAL globals);
  45. LINERESULT dialCloseCommHandle(LPDPDIAL globals);
  46. LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
  47. LPCSTR lpszDialAddress,
  48. LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet);
  49. LPSTR GetLineErrStr(LONG err);
  50. LPSTR GetCallStateStr(DWORD callState);
  51. LPSTR GetLineMsgStr(DWORD msg);
  52. #ifdef DEBUG
  53. extern LONG lineError(LONG err, LPSTR modName, DWORD lineNum);
  54. #define LINEERROR(err) (lineError(err, DPF_MODNAME, __LINE__))
  55. #else
  56. #define LINEERROR(err) (err)
  57. #endif
  58. /* dial initialize */
  59. #undef DPF_MODNAME
  60. #define DPF_MODNAME "dialInitialize"
  61. LINERESULT dialInitialize(HINSTANCE hInst, LPTSTR szAppName,
  62. LPDPCOMPORT lpComPort, LPDPDIAL *storage)
  63. {
  64. LPDPDIAL globals;
  65. LINERESULT lResult; /* Stores return code from TAPI calls */
  66. // create globals
  67. globals =(LPDPDIAL) GlobalAllocPtr(GHND, sizeof(DPDIAL));
  68. FAILWITHACTION(globals == NULL, lResult = LINEERR_NOMEM, Failure);
  69. DPF(3, "lineInitialize");
  70. DPF(3, "> hInstance: %08X", hInst);
  71. DPF(3, "> szAppName: %s", szAppName);
  72. // init the line
  73. lResult = lineInitialize(&globals->hLineApp,
  74. hInst,
  75. LineCallBackProc,
  76. szAppName,
  77. &globals->dwNumLines);
  78. FAILIF(LINEERROR(lResult), Failure);
  79. DPF(3, "< hLineApp: %08X", globals->hLineApp);
  80. DPF(3, "< dwNumLines: %d", globals->dwNumLines);
  81. // no lines available
  82. FAILWITHACTION(globals->dwNumLines == 0, lResult = LINEERR_NODEVICE, Failure);
  83. // store pointer to com port object
  84. globals->lpComPort = lpComPort;
  85. *storage = globals;
  86. return (SUCCESS);
  87. Failure:
  88. dialShutdown(globals);
  89. return (lResult);
  90. }
  91. /* dial shutdown */
  92. #undef DPF_MODNAME
  93. #define DPF_MODNAME "dialShutdown"
  94. LINERESULT dialShutdown(LPDPDIAL globals)
  95. {
  96. LINERESULT lResult;
  97. if (globals == NULL)
  98. return (SUCCESS);
  99. if (globals->hLineApp)
  100. {
  101. dialDropCall(globals);
  102. dialDeallocCall(globals);
  103. dialLineClose(globals);
  104. DPF(3, "lineShutdown");
  105. DPF(3, "> hLineApp: %08X", globals->hLineApp);
  106. lResult = lineShutdown(globals->hLineApp);
  107. LINEERROR(lResult);
  108. }
  109. GlobalFreePtr(globals);
  110. return (SUCCESS);
  111. }
  112. /* dialLineOpen - wrapper for lineOpen */
  113. #undef DPF_MODNAME
  114. #define DPF_MODNAME "dialLineOpen"
  115. LINERESULT dialLineOpen(LPDPDIAL globals, DWORD dwLine)
  116. {
  117. LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
  118. LPLINEDEVCAPS lpLineDevCaps = NULL;
  119. LINERESULT lResult;
  120. // fail if line is already open
  121. FAILWITHACTION(globals->hLine != 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  122. /* negotiate API version for each line */
  123. lResult = lineNegotiateAPIVersion(globals->hLineApp, dwLine,
  124. TAPIVERSION, TAPIVERSION,
  125. &globals->dwAPIVersion, &lineExtensionID);
  126. FAILIF(LINEERROR(lResult), Failure);
  127. lResult = dialGetDevCaps(globals, dwLine, globals->dwAPIVersion, &lpLineDevCaps);
  128. FAILIF(LINEERROR(lResult), Failure);
  129. /* check for supported media mode. If not datamodem, continue to next line */
  130. FAILWITHACTION(!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM),
  131. lResult = LINEERR_NODEVICE, Failure);
  132. DPF(3, "lineOpen");
  133. DPF(3, "> hLineApp: %08X", globals->hLineApp);
  134. DPF(3, "> dwDeviceID: %d", dwLine);
  135. // reset error tracking
  136. globals->dwCallError = CALL_OK;
  137. /* open the line that supports data modems */
  138. lResult = lineOpen( globals->hLineApp, dwLine, &globals->hLine,
  139. globals->dwAPIVersion, 0L,
  140. (DWORD_PTR) globals,
  141. LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM,
  142. NULL);
  143. FAILIF(LINEERROR(lResult), Failure);
  144. DPF(3, "< hLine: %08X", globals->hLine);
  145. /* if we are here then we found a compatible line */
  146. globals->dwLineID = dwLine;
  147. globals->dwCallState = LINECALLSTATE_IDLE; // line is now idle and ready to make/receive calls
  148. lResult = SUCCESS;
  149. Failure:
  150. if (lpLineDevCaps)
  151. GlobalFreePtr(lpLineDevCaps);
  152. return (lResult);
  153. }
  154. /* dialLineClose - wrapper for lineClose */
  155. #undef DPF_MODNAME
  156. #define DPF_MODNAME "dialLineClose"
  157. LINERESULT dialLineClose(LPDPDIAL globals)
  158. {
  159. LINERESULT lResult;
  160. // fail if line is already closed
  161. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  162. DPF(3, "lineClose");
  163. DPF(3, "> hLine: %08X", globals->hLine);
  164. lResult = lineClose(globals->hLine);
  165. LINEERROR(lResult);
  166. globals->hLine = 0;
  167. Failure:
  168. return (lResult);
  169. }
  170. /* dialMakeCall - wrapper for lineMakeCall */
  171. #undef DPF_MODNAME
  172. #define DPF_MODNAME "dialMakeCall"
  173. LINERESULT dialMakeCall(LPDPDIAL globals, LPTSTR szDestination)
  174. {
  175. LINECALLPARAMS callparams;
  176. LINERESULT lResult;
  177. // fail if line not open or if call is already open
  178. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  179. FAILWITHACTION(globals->hCall != 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  180. // set call parameters
  181. ZeroMemory(&callparams, sizeof(LINECALLPARAMS));
  182. callparams.dwBearerMode = LINEBEARERMODE_VOICE;
  183. callparams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  184. callparams.dwTotalSize = sizeof(LINECALLPARAMS);
  185. DPF(3, "lineMakeCall");
  186. DPF(3, "> hLine: %08X", globals->hLine);
  187. DPF(3, "> szDestAddr: \"%s\"", szDestination);
  188. lResult = lineMakeCall(globals->hLine, &globals->hCall, szDestination, 0, &callparams);
  189. // lResult will be > 0 if call is asynchronous
  190. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  191. FAILMSG(lResult == 0);
  192. DPF(3, "< hCall: %08X", globals->hCall);
  193. DPF(3, "< dwAsyncID: %d", lResult);
  194. globals->dwAsyncID = lResult; // store async ID
  195. lResult = SUCCESS;
  196. Failure:
  197. return (lResult);
  198. }
  199. /* dialDropCall - wrapper for lineDrop */
  200. #undef DPF_MODNAME
  201. #define DPF_MODNAME "dialDropCall"
  202. LINERESULT dialDropCall(LPDPDIAL globals)
  203. {
  204. MSG msg;
  205. DWORD dwStopTicks;
  206. LINERESULT lResult;
  207. // fail if line not open or if call not open
  208. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  209. FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  210. DPF(3, "lineDrop");
  211. DPF(3, "> hCall: %08X", globals->hCall);
  212. lResult = lineDrop(globals->hCall, NULL, 0);
  213. // lResult will be > 0 if call is asynchronous
  214. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  215. FAILMSG(lResult == 0);
  216. DPF(3, "< dwAsyncID: %d", lResult);
  217. globals->dwAsyncID = lResult; // store async ID
  218. // wait for call to get dropped
  219. dwStopTicks = GetTickCount() + LINEDROPTIMEOUT;
  220. while (GetTickCount() < dwStopTicks)
  221. {
  222. // see if reply has occured and we are idle
  223. if ((globals->dwAsyncID == 0) &&
  224. (globals->dwCallState == LINECALLSTATE_IDLE))
  225. {
  226. break;
  227. }
  228. // give TAPI a chance to call our callback
  229. if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  230. {
  231. TranslateMessage(&msg);
  232. DispatchMessage(&msg);
  233. }
  234. }
  235. lResult = SUCCESS;
  236. Failure:
  237. return (lResult);
  238. }
  239. /* dialDeallocCall - wrapper for lineDeallocCall */
  240. #undef DPF_MODNAME
  241. #define DPF_MODNAME "dialDeallocCall"
  242. LINERESULT dialDeallocCall(LPDPDIAL globals)
  243. {
  244. LINERESULT lResult;
  245. // fail if line not open or if call not open
  246. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  247. FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  248. // close the com port
  249. dialCloseCommHandle(globals);
  250. DPF(3, "lineDeallocateCall");
  251. DPF(3, "> hCall: %08X", globals->hCall);
  252. lResult = lineDeallocateCall(globals->hCall);
  253. LINEERROR(lResult);
  254. globals->hCall = 0;
  255. Failure:
  256. return (lResult);
  257. }
  258. /* dialIsConnected- returns TRUE if call is connected */
  259. #undef DPF_MODNAME
  260. #define DPF_MODNAME "dialIsConnected"
  261. BOOL dialIsConnected(LPDPDIAL globals)
  262. {
  263. // connected if we have a call handle and the state is connected
  264. if ((globals->hCall) &&
  265. (globals->dwCallState == LINECALLSTATE_CONNECTED))
  266. return (TRUE);
  267. else
  268. return (FALSE);
  269. }
  270. /* callback function */
  271. #undef DPF_MODNAME
  272. #define DPF_MODNAME "LineCallBackProc"
  273. void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
  274. DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3)
  275. {
  276. LPDPDIAL globals = (LPDPDIAL) dwInstance;
  277. DPF(3, "Line message: %s", GetLineMsgStr(dwMessage));
  278. switch (dwMessage)
  279. {
  280. case LINE_LINEDEVSTATE:
  281. break;
  282. case LINE_CALLSTATE:
  283. globals->dwCallState = dwParam1;
  284. DPF(3, " call state: %s", GetCallStateStr((DWORD)globals->dwCallState));
  285. switch (globals->dwCallState)
  286. {
  287. case LINECALLSTATE_OFFERING:
  288. ProcessOfferingState(globals, (HCALL) hDevice, (DWORD)dwParam3);
  289. break;
  290. case LINECALLSTATE_CONNECTED:
  291. ProcessConnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  292. break;
  293. case LINECALLSTATE_DISCONNECTED:
  294. ProcessDisconnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  295. break;
  296. case LINECALLSTATE_IDLE:
  297. ProcessIdleState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  298. break;
  299. case LINECALLSTATE_BUSY:
  300. break;
  301. }
  302. break;
  303. case LINE_REPLY:
  304. ProcessReplyMessage(globals, (DWORD)dwParam1, (LINERESULT) dwParam2);
  305. break;
  306. /* other messages that can be processed */
  307. case LINE_CLOSE:
  308. // the line has shut itself down
  309. globals->hLine = 0;
  310. globals->dwCallError = CALL_CLOSED;
  311. break;
  312. case LINE_ADDRESSSTATE:
  313. break;
  314. case LINE_CALLINFO:
  315. break;
  316. case LINE_DEVSPECIFIC:
  317. break;
  318. case LINE_DEVSPECIFICFEATURE:
  319. break;
  320. case LINE_GATHERDIGITS:
  321. break;
  322. case LINE_GENERATE:
  323. break;
  324. case LINE_MONITORDIGITS:
  325. break;
  326. case LINE_MONITORMEDIA:
  327. break;
  328. case LINE_MONITORTONE:
  329. break;
  330. } /* switch */
  331. } /* LineCallBackProc */
  332. /* ProcessOfferingState - handler for LINECALLSTATE_OFFERING state */
  333. #undef DPF_MODNAME
  334. #define DPF_MODNAME "ProcessOfferingState"
  335. void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege)
  336. {
  337. LINERESULT lResult;
  338. DDASSERT(hCall);
  339. DDASSERT(globals->hCall == 0);
  340. DDASSERT(globals->dwAsyncID == 0);
  341. DPF(3, " hCall: %08X", hCall);
  342. DPF(3, " privilege: %08X", (DWORD)dwCallPrivilege);
  343. // fail if we don't own the call
  344. FAILIF(dwCallPrivilege != LINECALLPRIVILEGE_OWNER, Failure);
  345. // answer the call
  346. lResult = lineAnswer(hCall, NULL, 0);
  347. // lResult will be > 0 if call is asynchronous
  348. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  349. FAILMSG(lResult == 0);
  350. globals->hCall = hCall; // store call handle
  351. globals->dwAsyncID = lResult; // store async ID
  352. Failure:
  353. return;
  354. }
  355. /* ProcessConnectedState - handler for LINECALLSTATE_CONNECTED state */
  356. #undef DPF_MODNAME
  357. #define DPF_MODNAME "ProcessConnectedState"
  358. void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  359. {
  360. LINERESULT lResult;
  361. HRESULT hr;
  362. DDASSERT(hCall);
  363. DDASSERT(globals->hCall);
  364. DDASSERT(globals->hCall == hCall);
  365. DPF(3, " hCall: %08X", hCall);
  366. DPF(3, " privilege: %08X", dwCallPrivilege);
  367. DPF(3, " detail: %08X", dwCallStateDetail);
  368. // get the id of the COM device connected to the modem
  369. // NOTE: once we get the handle, it is our responsibility to close it
  370. lResult = dialGetCommHandle(globals);
  371. FAILIF(LINEERROR(lResult), Failure);
  372. DPF(3, " hComPort: %08X", globals->hComm);
  373. // setup com port
  374. hr = globals->lpComPort->Setup(globals->lpComPort, globals->hComm);
  375. FAILIF(FAILED(hr), Failure);
  376. {
  377. DWORD dwBaudRate;
  378. lResult = dialGetBaudRate(globals, &dwBaudRate);
  379. }
  380. Failure:
  381. return;
  382. }
  383. /* ProcessDisconnectedState - handler for LINECALLSTATE_DISCONNECTED state */
  384. #undef DPF_MODNAME
  385. #define DPF_MODNAME "ProcessDisconnectedState"
  386. void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  387. {
  388. LINERESULT lResult;
  389. DDASSERT(hCall);
  390. DDASSERT(globals->hCall);
  391. DDASSERT(globals->hCall == hCall);
  392. DPF(3, " hCall: %08X", hCall);
  393. DPF(3, " privilege: %08X", dwCallPrivilege);
  394. DPF(3, " detail: %08X", dwCallStateDetail);
  395. // record error
  396. globals->dwCallError = CALL_DISCONNECTED;
  397. // shutdown com port and deallocate call handle
  398. lResult = dialDeallocCall(globals);
  399. FAILMSG(LINEERROR(lResult));
  400. }
  401. /* ProcessIdleState - handler for LINECALLSTATE_IDLE state */
  402. #undef DPF_MODNAME
  403. #define DPF_MODNAME "ProcessIdleState"
  404. void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  405. {
  406. DDASSERT(hCall);
  407. DPF(3, " hCall: %08X", hCall);
  408. DPF(3, " privilege: %08X", dwCallPrivilege);
  409. DPF(3, " detail: %08X", dwCallStateDetail);
  410. }
  411. /* ProcessReplyMessage - handler for LINE_REPLY message */
  412. #undef DPF_MODNAME
  413. #define DPF_MODNAME "ProcessReplyMessage"
  414. void ProcessReplyMessage(LPDPDIAL globals, DWORD dwAsyncID, LINERESULT lResult)
  415. {
  416. DDASSERT(dwAsyncID);
  417. DDASSERT(globals->dwAsyncID);
  418. DDASSERT(globals->dwAsyncID == dwAsyncID);
  419. DPF(3, " dwAsyncID: %d", dwAsyncID);
  420. DPF(3, " error: %d", lResult);
  421. // check for an error
  422. if (LINEERROR(lResult))
  423. globals->dwCallError = CALL_LINEERROR;
  424. // reset field so we know reply happened
  425. globals->dwAsyncID = 0;
  426. }
  427. /* dialGetDevCaps - wrapper for lineGetDevCaps */
  428. /* Bug #5400 -
  429. My trusty Compaq Presario returns two line devices. The second device says it
  430. needs 555 bytes for dev caps, but when you give it a pointer to a 555-byte block
  431. it actually writes 559 (!) bytes into the buffer! Whoah, Bessy!
  432. This makes Windows very unhappy in strange and magical ways.
  433. The fix is to start with a very large buffer (1024 bytes?) like all the samples do
  434. and then leave some slop in subsequent reallocs, which should hopefully clean up
  435. after these messy critters.
  436. */
  437. #define DEVCAPSINITIALSIZE 1024 // size of first alloc
  438. #define DEVCAPSSLOP 100 // extra space that loser service providers can party on
  439. #undef DPF_MODNAME
  440. #define DPF_MODNAME "dialGetDevCaps"
  441. LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet)
  442. {
  443. LPLINEDEVCAPS lpDevCaps;
  444. LINERESULT lResult;
  445. LPVOID lpTemp;
  446. // create a buffer for dev caps
  447. lpDevCaps = (LPLINEDEVCAPS) GlobalAllocPtr(GHND, DEVCAPSINITIALSIZE + DEVCAPSSLOP);
  448. FAILWITHACTION(lpDevCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  449. lpDevCaps->dwTotalSize = DEVCAPSINITIALSIZE;
  450. while (TRUE)
  451. {
  452. // get device caps
  453. lResult = lineGetDevCaps(globals->hLineApp, dwLine,
  454. dwAPIVersion, 0, lpDevCaps);
  455. if (lResult == SUCCESS)
  456. {
  457. // make sure there is enough space
  458. if (lpDevCaps->dwNeededSize <= lpDevCaps->dwTotalSize)
  459. break; // there is enough space, so exit
  460. }
  461. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  462. {
  463. LINEERROR(lResult);
  464. goto Failure;
  465. }
  466. // reallocate buffer if not big enough */
  467. lpTemp = GlobalReAllocPtr(lpDevCaps, lpDevCaps->dwNeededSize + DEVCAPSSLOP, 0);
  468. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  469. lpDevCaps = lpTemp;
  470. lpDevCaps->dwTotalSize = lpDevCaps->dwNeededSize;
  471. }
  472. *lpDevCapsRet = lpDevCaps;
  473. return (SUCCESS);
  474. Failure:
  475. if (lpDevCaps)
  476. GlobalFreePtr(lpDevCaps);
  477. return (lResult);
  478. }
  479. /* dialGetCallInfo - wrapper for lineGetCallInfo */
  480. #undef DPF_MODNAME
  481. #define DPF_MODNAME "dialGetCallInfo"
  482. LINERESULT dialGetCallInfo(LPDPDIAL globals, LPLINECALLINFO *lpCallInfoRet)
  483. {
  484. LPLINECALLINFO lpCallInfo;
  485. LINERESULT lResult;
  486. LPVOID lpTemp;
  487. // create a buffer for call info
  488. lpCallInfo = (LPLINECALLINFO) GlobalAllocPtr(GHND, sizeof(LINECALLINFO));
  489. FAILWITHACTION(lpCallInfo == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  490. lpCallInfo->dwTotalSize = sizeof(LINECALLINFO);
  491. while (TRUE)
  492. {
  493. // get device info
  494. lResult = lineGetCallInfo(globals->hCall, lpCallInfo);
  495. if (lResult == SUCCESS)
  496. {
  497. // make sure there is enough space
  498. if (lpCallInfo->dwNeededSize <= lpCallInfo->dwTotalSize)
  499. break; // there is enough space, so exit
  500. }
  501. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  502. {
  503. LINEERROR(lResult);
  504. goto Failure;
  505. }
  506. // reallocate buffer if not big enough */
  507. lpTemp = GlobalReAllocPtr(lpCallInfo, lpCallInfo->dwNeededSize, 0);
  508. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  509. lpCallInfo = lpTemp;
  510. lpCallInfo->dwTotalSize = lpCallInfo->dwNeededSize;
  511. }
  512. *lpCallInfoRet = lpCallInfo;
  513. return (SUCCESS);
  514. Failure:
  515. if (lpCallInfo)
  516. GlobalFreePtr(lpCallInfo);
  517. return (lResult);
  518. }
  519. /* dialGetBaudRate - get baud rate of current connecton */
  520. #undef DPF_MODNAME
  521. #define DPF_MODNAME "dialGetBaudRate"
  522. LINERESULT dialGetBaudRate(LPDPDIAL globals, LPDWORD lpdwBaudRate)
  523. {
  524. LPLINECALLINFO lpCallInfo;
  525. LINERESULT lResult;
  526. lResult = dialGetCallInfo(globals, &lpCallInfo);
  527. if LINEERROR(lResult)
  528. return (lResult);
  529. *lpdwBaudRate = lpCallInfo->dwRate;
  530. GlobalFreePtr(lpCallInfo);
  531. return (SUCCESS);
  532. }
  533. /* dialGetTranslateCaps - wrapper for lineGetTranslateCaps */
  534. #undef DPF_MODNAME
  535. #define DPF_MODNAME "dialGetTranslateCaps"
  536. LINERESULT dialGetTranslateCaps(LPDPDIAL globals, DWORD dwAPIVersion, LPLINETRANSLATECAPS *lpTranslateCapsRet)
  537. {
  538. LPLINETRANSLATECAPS lpTranslateCaps;
  539. LPVOID lpTemp;
  540. LINERESULT lResult;
  541. // create a buffer for translate caps
  542. lpTranslateCaps = (LPLINETRANSLATECAPS) GlobalAllocPtr(GHND, sizeof(LINETRANSLATECAPS));
  543. FAILWITHACTION(lpTranslateCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  544. lpTranslateCaps->dwTotalSize = sizeof(LINETRANSLATECAPS);
  545. while (TRUE)
  546. {
  547. // get translate caps
  548. lResult = lineGetTranslateCaps(globals->hLineApp, dwAPIVersion, lpTranslateCaps);
  549. if (lResult == SUCCESS)
  550. {
  551. // make sure there is enough space
  552. if (lpTranslateCaps->dwNeededSize <= lpTranslateCaps->dwTotalSize)
  553. break; // there is enough space, so exit
  554. }
  555. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  556. {
  557. LINEERROR(lResult);
  558. goto Failure;
  559. }
  560. // reallocate buffer if not big enough */
  561. lpTemp = GlobalReAllocPtr(lpTranslateCaps, lpTranslateCaps->dwNeededSize, 0);
  562. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  563. lpTranslateCaps = lpTemp;
  564. lpTranslateCaps->dwTotalSize = lpTranslateCaps->dwNeededSize;
  565. }
  566. *lpTranslateCapsRet = lpTranslateCaps;
  567. return (SUCCESS);
  568. Failure:
  569. if (lpTranslateCaps)
  570. GlobalFreePtr(lpTranslateCaps);
  571. return (lResult);
  572. }
  573. /* dialGetCommHandle - wrapper for lineGetID */
  574. #undef DPF_MODNAME
  575. #define DPF_MODNAME "dialGetCommHandle"
  576. /* structure returned by Unimodem which contains device handle and name */
  577. typedef struct {
  578. HANDLE hComm;
  579. CHAR szDeviceName[1];
  580. } COMMID, *LPCOMMID;
  581. LINERESULT dialGetCommHandle(LPDPDIAL globals)
  582. {
  583. LPCOMMID lpCommID;
  584. VARSTRING *vs, *temp;
  585. LINERESULT lResult;
  586. vs = (VARSTRING *) GlobalAllocPtr(GHND, sizeof(VARSTRING));
  587. FAILWITHACTION(vs == NULL, lResult = LINEERR_NOMEM, Failure);
  588. vs->dwTotalSize = sizeof(VARSTRING);
  589. vs->dwStringFormat = STRINGFORMAT_BINARY;
  590. while (TRUE)
  591. {
  592. // get line ID
  593. lResult = lineGetID(0, 0L, globals->hCall, LINECALLSELECT_CALL, vs, "comm/datamodem");
  594. if (lResult == SUCCESS)
  595. {
  596. // make sure there is enough space
  597. if (vs->dwNeededSize <= vs->dwTotalSize)
  598. break; // there is enough space, so exit
  599. }
  600. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  601. {
  602. LINEERROR(lResult);
  603. goto Failure;
  604. }
  605. // reallocate buffer if not big enough */
  606. temp = GlobalReAllocPtr(vs, vs->dwNeededSize, 0);
  607. FAILWITHACTION(temp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  608. vs = temp;
  609. vs->dwTotalSize = vs->dwNeededSize;
  610. }
  611. lpCommID = (LPCOMMID) ((LPSTR)vs + vs->dwStringOffset);
  612. // lstrcpy(globals->szDeviceName, cid->szDeviceName);
  613. globals->hComm = lpCommID->hComm;
  614. Failure:
  615. if (vs)
  616. GlobalFreePtr(vs);
  617. return (lResult);
  618. }
  619. /* dialCloseCommHandle - make sure com port is closed */
  620. /* NOTE: As per the docs for the "comm/datamodem" device class,
  621. the handle to the com port returned by lineGetID() MUST be explictly
  622. closed using CloseHandle() or you will not be able to to open this
  623. line again!
  624. */
  625. #undef DPF_MODNAME
  626. #define DPF_MODNAME "dialCloseCommHandle"
  627. LINERESULT dialCloseCommHandle(LPDPDIAL globals)
  628. {
  629. HANDLE hCom;
  630. // make sure the com port globals are available
  631. if (globals->lpComPort)
  632. {
  633. // get handle to com port
  634. hCom = globals->lpComPort->GetHandle(globals->lpComPort);
  635. // make sure its closed down
  636. if (hCom)
  637. {
  638. globals->lpComPort->Shutdown(globals->lpComPort);
  639. CloseHandle(hCom);
  640. }
  641. }
  642. return (SUCCESS);
  643. }
  644. /* dialTranslateAddress - wrapper for lineTranslateAddress */
  645. #undef DPF_MODNAME
  646. #define DPF_MODNAME "dialTranslateAddress"
  647. LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
  648. LPCSTR lpszDialAddress,
  649. LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet)
  650. {
  651. LPLINETRANSLATEOUTPUT lpLineTranslateOutput;
  652. LPVOID lpTemp;
  653. LINERESULT lResult;
  654. // create a buffer for translate caps
  655. lpLineTranslateOutput = (LPLINETRANSLATEOUTPUT) GlobalAllocPtr(GHND, sizeof(LINETRANSLATEOUTPUT));
  656. FAILWITHACTION(lpLineTranslateOutput == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  657. lpLineTranslateOutput->dwTotalSize = sizeof(LINETRANSLATEOUTPUT);
  658. while (TRUE)
  659. {
  660. // translate address
  661. lResult = lineTranslateAddress(globals->hLineApp, dwDeviceID, dwAPIVersion,
  662. lpszDialAddress, 0, LINETRANSLATEOPTION_CANCELCALLWAITING,
  663. lpLineTranslateOutput);
  664. if (lResult == SUCCESS)
  665. {
  666. // make sure there is enough space
  667. if (lpLineTranslateOutput->dwNeededSize <= lpLineTranslateOutput->dwTotalSize)
  668. break; // there is enough space, so exit
  669. }
  670. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  671. {
  672. LINEERROR(lResult);
  673. goto Failure;
  674. }
  675. // reallocate buffer if not big enough */
  676. lpTemp = GlobalReAllocPtr(lpLineTranslateOutput, lpLineTranslateOutput->dwNeededSize, 0);
  677. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  678. lpLineTranslateOutput = lpTemp;
  679. lpLineTranslateOutput->dwTotalSize = lpLineTranslateOutput->dwNeededSize;
  680. }
  681. *lpLineTranslateOutputRet = lpLineTranslateOutput;
  682. return (SUCCESS);
  683. Failure:
  684. if (lpLineTranslateOutput)
  685. GlobalFreePtr(lpLineTranslateOutput);
  686. return (lResult);
  687. }
  688. LINERESULT dialTranslateDialog(LPDPDIAL globals, HWND hWnd,
  689. DWORD dwDeviceID, LPTSTR szPhoneNumber)
  690. {
  691. LINERESULT lResult;
  692. lResult = lineTranslateDialog(globals->hLineApp, dwDeviceID,
  693. TAPIVERSION, hWnd, szPhoneNumber);
  694. return (lResult);
  695. }
  696. //
  697. // FUNCTION: void dialFillModemComboBox(HWND)
  698. //
  699. // PURPOSE: Fills the modem control with the available line devices.
  700. //
  701. // PARAMETERS:
  702. // hwndDlg - handle to the current "Dial" dialog
  703. //
  704. // RETURN VALUE:
  705. // none
  706. //
  707. // COMMENTS:
  708. //
  709. // This function enumerates through all the TAPI line devices and
  710. // queries each for the device name. The device name is then put into
  711. // the 'TAPI Line' control. These device names are kept in order rather
  712. // than sorted. This allows "Dial" to know which device ID the user
  713. // selected just by the knowing the index of the selected string.
  714. //
  715. // There are default values if there isn't a device name, if there is
  716. // an error on the device, or if the device name is an empty string.
  717. // The device name is also checked to make sure it is null terminated.
  718. //
  719. // Note that a Legacy API Version is negotiated. Since the fields in
  720. // the LINEDEVCAPS structure that we are interested in haven't moved, we
  721. // can negotiate a lower API Version than this sample is designed for
  722. // and still be able to access the necessary structure members.
  723. //
  724. // The first line that is usable by TapiComm is selected as the 'default'
  725. // line. Also note that if there was a previously selected line, this
  726. // remains the default line. This would likely only occur if this
  727. // function is called after the dialog has initialized once; for example,
  728. // if a new line is added.
  729. //
  730. //
  731. LINERESULT dialGetModemName(LPDPDIAL globals, DWORD dwDeviceID,
  732. LPSTR lpszModemName, DWORD dwModemNameSize)
  733. {
  734. LPLINEDEVCAPS lpLineDevCaps = NULL;
  735. LPSTR lpszLineName;
  736. LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
  737. DWORD dwAPIVersion; // api version
  738. DWORD dwStrSize;
  739. LINERESULT lResult;
  740. /* negotiate API version for each line */
  741. lResult = lineNegotiateAPIVersion(globals->hLineApp, dwDeviceID,
  742. TAPIVERSION, TAPIVERSION,
  743. &dwAPIVersion, &lineExtensionID);
  744. if LINEERROR(lResult)
  745. goto FAILURE;
  746. lResult = dialGetDevCaps(globals, dwDeviceID, dwAPIVersion, &lpLineDevCaps);
  747. if LINEERROR(lResult)
  748. goto FAILURE;
  749. if ((lpLineDevCaps->dwLineNameSize) &&
  750. (lpLineDevCaps->dwLineNameOffset) &&
  751. (lpLineDevCaps->dwStringFormat == STRINGFORMAT_ASCII))
  752. {
  753. // This is the name of the device.
  754. lpszLineName = ((char *) lpLineDevCaps) + lpLineDevCaps->dwLineNameOffset;
  755. if (lpszLineName[0] != '\0')
  756. {
  757. // Reverse indented to make this fit
  758. // Make sure the device name is null terminated.
  759. if (lpszLineName[lpLineDevCaps->dwLineNameSize -1] != '\0')
  760. {
  761. // If the device name is not null terminated, null
  762. // terminate it. Yes, this looses the end character.
  763. // Its a bug in the service provider.
  764. lpszLineName[lpLineDevCaps->dwLineNameSize-1] = '\0';
  765. DPF(0, "Device name for device 0x%lx is not null terminated.", dwDeviceID);
  766. }
  767. }
  768. else // Line name started with a NULL.
  769. {
  770. lResult = LINEERR_OPERATIONFAILED;
  771. goto FAILURE;
  772. }
  773. }
  774. else // DevCaps doesn't have a valid line name. Unnamed.
  775. {
  776. lResult = LINEERR_OPERATIONFAILED;
  777. goto FAILURE;
  778. }
  779. // return modem name (make sure it fits)
  780. dwStrSize = strlen(lpszLineName) + 1;
  781. if (dwStrSize <= dwModemNameSize)
  782. CopyMemory(lpszModemName, lpszLineName, dwStrSize);
  783. else
  784. {
  785. CopyMemory(lpszModemName, lpszLineName, dwModemNameSize - 1);
  786. lpszModemName[dwModemNameSize - 1] = '\0';
  787. }
  788. FAILURE:
  789. if (lpLineDevCaps)
  790. GlobalFreePtr(lpLineDevCaps);
  791. return (lResult);
  792. }
  793. LINERESULT dialGetModemList(LPDPDIAL globals, BOOL bAnsi, LPVOID *lplpData, LPDWORD lpdwDataSize)
  794. {
  795. DWORD dwDeviceID;
  796. CHAR szModemName[MAXSTRINGSIZE];
  797. LPBYTE lpData;
  798. DWORD dwDataSize, dwStrBytes, dwStrLen;
  799. LINERESULT lResult;
  800. // make space for all possible strings plus terminating null
  801. lpData = (LPBYTE) GlobalAllocPtr(GHND, globals->dwNumLines * MAXSTRINGSIZE * sizeof(WCHAR) + sizeof(WCHAR));
  802. FAILWITHACTION(lpData == NULL, lResult = LINEERR_NOMEM, Failure);
  803. dwDataSize = 0;
  804. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  805. {
  806. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  807. if LINEERROR(lResult)
  808. continue;
  809. if (bAnsi)
  810. {
  811. dwStrBytes = (lstrlen(szModemName) + 1) * sizeof(CHAR);
  812. memcpy(lpData + dwDataSize, szModemName, dwStrBytes);
  813. }
  814. else
  815. {
  816. // NOTE: AnsiToWide returns the character count INCLUDING the terminating null character
  817. dwStrLen = AnsiToWide((LPWSTR) (lpData + dwDataSize), szModemName, MAXSTRINGSIZE * sizeof(WCHAR));
  818. dwStrBytes = dwStrLen * sizeof(WCHAR);
  819. }
  820. dwDataSize += dwStrBytes;
  821. }
  822. // put a null at end of list to terminate it
  823. if (bAnsi)
  824. {
  825. *(lpData + dwDataSize) = 0;
  826. dwDataSize += sizeof(CHAR);
  827. }
  828. else
  829. {
  830. *((LPWSTR) (lpData + dwDataSize)) = 0;
  831. dwDataSize += sizeof(WCHAR);
  832. }
  833. // return buffer pointer and size
  834. *lplpData = lpData;
  835. *lpdwDataSize = dwDataSize;
  836. return (SUCCESS);
  837. Failure:
  838. return (lResult);
  839. }
  840. void dialFillModemComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultDevice)
  841. {
  842. DWORD dwDeviceID;
  843. CHAR szModemName[MAXSTRINGSIZE];
  844. LINERESULT lResult;
  845. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  846. {
  847. //
  848. // Attempt to get the modem name. If this fails, don't add the modem
  849. // to the dialog.
  850. //
  851. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  852. if ( LINEERROR(lResult) == FALSE )
  853. {
  854. //
  855. // This line appears to be usable, put the device name into the
  856. // dialog control and associate the TAPI modem ID with it
  857. //
  858. lResult = (DWORD) SendDlgItemMessage(hwndDlg, item,
  859. CB_ADDSTRING, 0, (LPARAM) szModemName);
  860. if ( lResult != CB_ERRSPACE )
  861. {
  862. DWORD_PTR TempReturn;
  863. //
  864. // We've managed to get this entry into the control, make sure
  865. // we associate the proper TAPI modem ID with this item. This
  866. // should never fail.
  867. //
  868. TempReturn = SendDlgItemMessage( hwndDlg, item, CB_SETITEMDATA, lResult, dwDeviceID );
  869. DDASSERT( TempReturn != CB_ERR );
  870. // If this line is usable and we don't have a default initial
  871. // line yet, make this the initial line.
  872. if (dwDefaultDevice == MAXDWORD)
  873. dwDefaultDevice = lResult;
  874. }
  875. }
  876. }
  877. if (dwDefaultDevice == MAXDWORD)
  878. dwDefaultDevice = 0;
  879. // Set the initial default line
  880. SendDlgItemMessage(hwndDlg, item,
  881. CB_SETCURSEL, dwDefaultDevice, 0);
  882. }
  883. LRESULT dialGetDeviceIDFromName(LPDPDIAL globals, LPCSTR szTargetName, DWORD *lpdwDeviceID)
  884. {
  885. DWORD dwDeviceID;
  886. CHAR szModemName[MAXSTRINGSIZE];
  887. LINERESULT lResult;
  888. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  889. {
  890. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  891. if LINEERROR(lResult)
  892. continue;
  893. if (strcmp(szModemName, szTargetName) == 0)
  894. {
  895. *lpdwDeviceID = dwDeviceID;
  896. return (SUCCESS);
  897. }
  898. }
  899. return (LINEERR_OPERATIONFAILED);
  900. }
  901. //
  902. // FUNCTION: void dialFillLocationComboBox(HWND)
  903. //
  904. // PURPOSE: Fills the control with the available calling from locations.
  905. //
  906. // PARAMETERS:
  907. // hwndDlg - handle to the current "Dial" dialog
  908. //
  909. // RETURN VALUE:
  910. // none
  911. //
  912. // COMMENTS:
  913. //
  914. //
  915. void dialFillLocationComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultLocation)
  916. {
  917. LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  918. LPLINELOCATIONENTRY lpLocationEntry;
  919. DWORD dwCounter;
  920. LONG index;
  921. LINERESULT lResult;
  922. // get translate caps
  923. lResult = dialGetTranslateCaps(globals, TAPIVERSION, &lpTranslateCaps);
  924. if LINEERROR(lResult)
  925. return;
  926. // Find the location information in the TRANSLATECAPS
  927. lpLocationEntry = (LPLINELOCATIONENTRY)
  928. (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  929. // First empty the combobox
  930. SendDlgItemMessage(hwndDlg, item, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0);
  931. // enumerate all the locations
  932. for (dwCounter = 0; dwCounter < lpTranslateCaps->dwNumLocations; dwCounter++)
  933. {
  934. // Put each one into the combobox
  935. index = (DWORD)SendDlgItemMessage(hwndDlg, item,
  936. CB_ADDSTRING,
  937. (WPARAM) 0,
  938. (LPARAM) (((LPBYTE) lpTranslateCaps) +
  939. lpLocationEntry[dwCounter].dwLocationNameOffset));
  940. // Is this location the 'current' location?
  941. if (lpLocationEntry[dwCounter].dwPermanentLocationID ==
  942. lpTranslateCaps->dwCurrentLocationID)
  943. {
  944. // Set this to be the active location.
  945. SendDlgItemMessage(hwndDlg, item, CB_SETCURSEL, (WPARAM) index, (LPARAM) 0);
  946. }
  947. }
  948. if (lpTranslateCaps)
  949. GlobalFreePtr(lpTranslateCaps);
  950. }
  951. char gTempStr[200];
  952. LONG lineError(LONG err, LPSTR modName, DWORD lineNum)
  953. {
  954. if (err)
  955. DPF(0, "TAPI line error in %s at line %d : %s", modName, lineNum, GetLineErrStr(err));
  956. return (err);
  957. }
  958. LPSTR GetCallStateStr(DWORD callState)
  959. {
  960. switch (callState)
  961. {
  962. case LINECALLSTATE_IDLE: return ("LINECALLSTATE_IDLE");
  963. case LINECALLSTATE_OFFERING: return ("LINECALLSTATE_OFFERING");
  964. case LINECALLSTATE_ACCEPTED: return ("LINECALLSTATE_ACCEPTED");
  965. case LINECALLSTATE_DIALTONE: return ("LINECALLSTATE_DIALTONE");
  966. case LINECALLSTATE_DIALING: return ("LINECALLSTATE_DIALING");
  967. case LINECALLSTATE_RINGBACK: return ("LINECALLSTATE_RINGBACK");
  968. case LINECALLSTATE_BUSY: return ("LINECALLSTATE_BUSY");
  969. case LINECALLSTATE_SPECIALINFO: return ("LINECALLSTATE_SPECIALINFO");
  970. case LINECALLSTATE_CONNECTED: return ("LINECALLSTATE_CONNECTED");
  971. case LINECALLSTATE_PROCEEDING: return ("LINECALLSTATE_PROCEEDING");
  972. case LINECALLSTATE_ONHOLD: return ("LINECALLSTATE_ONHOLD");
  973. case LINECALLSTATE_CONFERENCED: return ("LINECALLSTATE_CONFERENCED");
  974. case LINECALLSTATE_ONHOLDPENDCONF: return ("LINECALLSTATE_ONHOLDPENDCONF");
  975. case LINECALLSTATE_ONHOLDPENDTRANSFER: return ("LINECALLSTATE_ONHOLDPENDTRANSFER");
  976. case LINECALLSTATE_DISCONNECTED: return ("LINECALLSTATE_DISCONNECTED");
  977. case LINECALLSTATE_UNKNOWN: return ("LINECALLSTATE_UNKNOWN");
  978. }
  979. wsprintf(gTempStr, "UNKNOWN CALL STATE = %lu", callState);
  980. return (gTempStr);
  981. }
  982. LPSTR GetLineMsgStr(DWORD msg)
  983. {
  984. switch (msg)
  985. {
  986. case LINE_ADDRESSSTATE: return ("LINE_ADDRESSSTATE");
  987. case LINE_CALLINFO: return ("LINE_CALLINFO");
  988. case LINE_CALLSTATE: return ("LINE_CALLSTATE");
  989. case LINE_CLOSE: return ("LINE_CLOSE");
  990. case LINE_DEVSPECIFIC: return ("LINE_DEVSPECIFIC");
  991. case LINE_DEVSPECIFICFEATURE: return ("LINE_DEVSPECIFICFEATURE");
  992. case LINE_GATHERDIGITS: return ("LINE_GATHERDIGITS");
  993. case LINE_GENERATE: return ("LINE_GENERATE");
  994. case LINE_LINEDEVSTATE: return ("LINE_LINEDEVSTATE");
  995. case LINE_MONITORDIGITS: return ("LINE_MONITORDIGITS");
  996. case LINE_MONITORMEDIA: return ("LINE_MONITORMEDIA");
  997. case LINE_MONITORTONE: return ("LINE_MONITORTONE");
  998. case LINE_REPLY: return ("LINE_REPLY");
  999. case LINE_REQUEST: return ("LINE_REQUEST");
  1000. }
  1001. wsprintf(gTempStr, "UNKNOWN LINE MESSAGE = %lu", msg);
  1002. return (gTempStr);
  1003. }
  1004. LPSTR GetLineErrStr(LONG err)
  1005. {
  1006. switch (err)
  1007. {
  1008. case LINEERR_ADDRESSBLOCKED: return ("LINEERR_ADDRESSBLOCKED");
  1009. case LINEERR_ALLOCATED: return ("LINEERR_ALLOCATED");
  1010. case LINEERR_BADDEVICEID: return ("LINEERR_BADDEVICEID");
  1011. case LINEERR_BEARERMODEUNAVAIL: return ("LINEERR_BEARERMODEUNAVAIL");
  1012. case LINEERR_CALLUNAVAIL: return ("LINEERR_CALLUNAVAIL");
  1013. case LINEERR_COMPLETIONOVERRUN: return ("LINEERR_COMPLETIONOVERRUN");
  1014. case LINEERR_CONFERENCEFULL: return ("LINEERR_CONFERENCEFULL");
  1015. case LINEERR_DIALBILLING: return ("LINEERR_DIALBILLING");
  1016. case LINEERR_DIALQUIET: return ("LINEERR_DIALQUIET");
  1017. case LINEERR_DIALDIALTONE: return ("LINEERR_DIALDIALTONE");
  1018. case LINEERR_DIALPROMPT: return ("LINEERR_DIALPROMPT");
  1019. case LINEERR_INCOMPATIBLEAPIVERSION: return ("LINEERR_INCOMPATIBLEAPIVERSION");
  1020. case LINEERR_INCOMPATIBLEEXTVERSION: return ("LINEERR_INCOMPATIBLEEXTVERSION");
  1021. case LINEERR_INIFILECORRUPT: return ("LINEERR_INIFILECORRUPT");
  1022. case LINEERR_INUSE: return ("LINEERR_INUSE");
  1023. case LINEERR_INVALADDRESS: return ("LINEERR_INVALADDRESS");
  1024. case LINEERR_INVALADDRESSID: return ("LINEERR_INVALADDRESSID");
  1025. case LINEERR_INVALADDRESSMODE: return ("LINEERR_INVALADDRESSMODE");
  1026. case LINEERR_INVALADDRESSSTATE: return ("LINEERR_INVALADDRESSSTATE");
  1027. case LINEERR_INVALAPPHANDLE: return ("LINEERR_INVALAPPHANDLE");
  1028. case LINEERR_INVALAPPNAME: return ("LINEERR_INVALAPPNAME");
  1029. case LINEERR_INVALBEARERMODE: return ("LINEERR_INVALBEARERMODE");
  1030. case LINEERR_INVALCALLCOMPLMODE: return ("LINEERR_INVALCALLCOMPLMODE");
  1031. case LINEERR_INVALCALLHANDLE: return ("LINEERR_INVALCALLHANDLE");
  1032. case LINEERR_INVALCALLPARAMS: return ("LINEERR_INVALCALLPARAMS");
  1033. case LINEERR_INVALCALLPRIVILEGE: return ("LINEERR_INVALCALLPRIVILEGE");
  1034. case LINEERR_INVALCALLSELECT: return ("LINEERR_INVALCALLSELECT");
  1035. case LINEERR_INVALCALLSTATE: return ("LINEERR_INVALCALLSTATE");
  1036. case LINEERR_INVALCALLSTATELIST: return ("LINEERR_INVALCALLSTATELIST");
  1037. case LINEERR_INVALCARD: return ("LINEERR_INVALCARD");
  1038. case LINEERR_INVALCOMPLETIONID: return ("LINEERR_INVALCOMPLETIONID");
  1039. case LINEERR_INVALCONFCALLHANDLE: return ("LINEERR_INVALCONFCALLHANDLE");
  1040. case LINEERR_INVALCONSULTCALLHANDLE: return ("LINEERR_INVALCONSULTCALLHANDLE");
  1041. case LINEERR_INVALCOUNTRYCODE: return ("LINEERR_INVALCOUNTRYCODE");
  1042. case LINEERR_INVALDEVICECLASS: return ("LINEERR_INVALDEVICECLASS");
  1043. case LINEERR_INVALDIGITLIST: return ("LINEERR_INVALDIGITLIST");
  1044. case LINEERR_INVALDIGITMODE: return ("LINEERR_INVALDIGITMODE");
  1045. case LINEERR_INVALDIGITS: return ("LINEERR_INVALDIGITS");
  1046. case LINEERR_INVALFEATURE: return ("LINEERR_INVALFEATURE");
  1047. case LINEERR_INVALGROUPID: return ("LINEERR_INVALGROUPID");
  1048. case LINEERR_INVALLINEHANDLE: return ("LINEERR_INVALLINEHANDLE");
  1049. case LINEERR_INVALLINESTATE: return ("LINEERR_INVALLINESTATE");
  1050. case LINEERR_INVALLOCATION: return ("LINEERR_INVALLOCATION");
  1051. case LINEERR_INVALMEDIALIST: return ("LINEERR_INVALMEDIALIST");
  1052. case LINEERR_INVALMEDIAMODE: return ("LINEERR_INVALMEDIAMODE");
  1053. case LINEERR_INVALMESSAGEID: return ("LINEERR_INVALMESSAGEID");
  1054. case LINEERR_INVALPARAM: return ("LINEERR_INVALPARAM");
  1055. case LINEERR_INVALPARKMODE: return ("LINEERR_INVALPARKMODE");
  1056. case LINEERR_INVALPOINTER: return ("LINEERR_INVALPOINTER");
  1057. case LINEERR_INVALPRIVSELECT: return ("LINEERR_INVALPRIVSELECT");
  1058. case LINEERR_INVALRATE: return ("LINEERR_INVALRATE");
  1059. case LINEERR_INVALREQUESTMODE: return ("LINEERR_INVALREQUESTMODE");
  1060. case LINEERR_INVALTERMINALID: return ("LINEERR_INVALTERMINALID");
  1061. case LINEERR_INVALTERMINALMODE: return ("LINEERR_INVALTERMINALMODE");
  1062. case LINEERR_INVALTIMEOUT: return ("LINEERR_INVALTIMEOUT");
  1063. case LINEERR_INVALTONE: return ("LINEERR_INVALTONE");
  1064. case LINEERR_INVALTONELIST: return ("LINEERR_INVALTONELIST");
  1065. case LINEERR_INVALTONEMODE: return ("LINEERR_INVALTONEMODE");
  1066. case LINEERR_INVALTRANSFERMODE: return ("LINEERR_INVALTRANSFERMODE");
  1067. case LINEERR_LINEMAPPERFAILED: return ("LINEERR_LINEMAPPERFAILED");
  1068. case LINEERR_NOCONFERENCE: return ("LINEERR_NOCONFERENCE");
  1069. case LINEERR_NODEVICE: return ("LINEERR_NODEVICE");
  1070. case LINEERR_NODRIVER: return ("LINEERR_NODRIVER");
  1071. case LINEERR_NOMEM: return ("LINEERR_NOMEM");
  1072. case LINEERR_NOMULTIPLEINSTANCE: return ("LINEERR_NOMULTIPLEINSTANCE");
  1073. case LINEERR_NOREQUEST: return ("LINEERR_NOREQUEST");
  1074. case LINEERR_NOTOWNER: return ("LINEERR_NOTOWNER");
  1075. case LINEERR_NOTREGISTERED: return ("LINEERR_NOTREGISTERED");
  1076. case LINEERR_OPERATIONFAILED: return ("LINEERR_OPERATIONFAILED");
  1077. case LINEERR_OPERATIONUNAVAIL: return ("LINEERR_OPERATIONUNAVAIL");
  1078. case LINEERR_RATEUNAVAIL: return ("LINEERR_RATEUNAVAIL");
  1079. case LINEERR_REINIT: return ("LINEERR_REINIT");
  1080. case LINEERR_RESOURCEUNAVAIL: return ("LINEERR_RESOURCEUNAVAIL");
  1081. case LINEERR_STRUCTURETOOSMALL: return ("LINEERR_STRUCTURETOOSMALL");
  1082. case LINEERR_TARGETNOTFOUND: return ("LINEERR_TARGETNOTFOUND");
  1083. case LINEERR_TARGETSELF: return ("LINEERR_TARGETSELF");
  1084. case LINEERR_UNINITIALIZED: return ("LINEERR_UNINITIALIZED");
  1085. case LINEERR_USERUSERINFOTOOBIG: return ("LINEERR_USERUSERINFOTOOBIG");
  1086. }
  1087. wsprintf(gTempStr, "UNKNOWN LINE ERROR = %ld", err);
  1088. return (gTempStr);
  1089. }